对象数组的对象。获取具有相同属性的所有值的长度

Posted

技术标签:

【中文标题】对象数组的对象。获取具有相同属性的所有值的长度【英文标题】:Object of array of objects. Get the length of all values with the same property 【发布时间】:2019-06-05 15:59:08 【问题描述】:

我有一个看起来像这样的对象:

    var obj = 
      "array1": [
        
          "label": "something1",
          "ref": "option2a"
        ,
        
          "label": "something2",
          "ref": "option2b"
        ,
        
          "label": "something3",
          "ref": "option2a"
        ,
        
          "label": "something4",
          "ref": "option2a"
        ,
        
          "label": "something5",
          "ref": "option2a"
        
      ],
      "array2": [
        
          "label": "something6 is the longest label",
          "ref": "option3a"
        ,
        
          "label": "Other",
          "ref": "option3b"
        
      ]
    

我想得到最长标签的长度。在这种情况下,我想返回 17。因为最长的标签是“somethinglongest”,长度为 17。

【问题讨论】:

到目前为止你有什么尝试? somethinglongest的长度只有16... 好问题。使用 map()... (tripple dot notaion) 来解构数组非常棒。 【参考方案1】:

直截了当的方法:

let obj = 
      "array1": [
        "label": "something1", "ref": "option2a",
        "label": "something2", "ref": "option2b",
        "label": "something3", "ref": "option2a",
        "label": "something4", "ref": "option2a",
        "label": "something5", "ref": "option2a"
      ],
      "array2": [
        "label": "something6 is the longest label", "ref": "option3a",
        "label": "Other", "ref": "option3b"
      ]
;

let longest = 0
for (key in obj)
    if (!obj.hasOwnProperty(key)) continue;
    for (let x of obj[key])
        if (x.label.length > longest)
            longest = x.label.length;
    

console.log(longest);

【讨论】:

谢谢,我怎样才能让它与有空格的标签一起工作? 我收到以下错误:Uncaught TypeError: Cannot use 'in' operator to search 'label' in Calculate Your Total @Mandalina 恐怕我无能为力,因为此错误是由您自己的代码引起的...如果您单击问题中的“运行代码 sn-p”蓝色按钮,它是清除我的代码工作正常。 你好@cybernaut 我再次补充了这个问题,这对于包含对象和数组的对象如何工作? @Mandalina 对不起,每个问题一个问题!你必须问一个新的(你可以把它链接到这个,我会看看)。【参考方案2】:

您可以使用这 1 行语句。

let maxLen = Math.max(...Object.keys(obj).map((key) => Math.max(...obj[key].map((o) => o.label.length))));

节点 REPL 示例

> var obj = 
...       "array1": [
...         
.....           "label": "something1",
.....           "ref": "option2a"
.....         ,
...         
.....           "label": "something2",
.....           "ref": "option2b"
.....         ,
...         
.....           "label": "something3",
.....           "ref": "option2a"
.....         ,
...         
.....           "label": "something4",
.....           "ref": "option2a"
.....         ,
...         
.....           "label": "something5",
.....           "ref": "option2a"
.....         
...       ],
...       "array2": [
...         
.....           "label": "somethinglongest",
.....           "ref": "option3a"
.....         ,
...         
.....           "label": "Other",
.....           "ref": "option3b"
.....         
...       ]
...     
undefined
>
> Math.max(...Object.keys(obj).map((key) => Math.max(...obj[key].map((o) => o.label.length))))
16
>

详细概述

let keys = Object.keys(obj);

let maxLens = keys.map((key) => 
    let arr = obj[key];
    return Math.max(...arr.map((o) => o.label.length))
);

let max = Math.max(...maxLens);

console.log(keys);    // [ 'array1', 'array2' ]
console.log(maxLens); // [ 10, 16 ]
console.log(max);     // 16

这里有一个可以帮助你的例子。

> Math.max(4, 5, 7)
7
>
> Math.max([4, 5, 7])
NaN
>
> Math.max(...[6, 7])
7
>
> let a = [2, 4, 5]
undefined
>
> a2 = a.map((num) => num ** 2)
[ 4, 16, 25 ]
>
> a3 = a.map((num) => num + 2)
[ 4, 6, 7 ]
>

【讨论】:

非常感谢您的回答!我已更新问题以包含其中包含空格的标签。你能告诉我这将如何工作以包含更新吗?我喜欢步行。 所以在这种情况下,相同的代码可以工作,但它也会计算空格。你想跳过空格还是可以?谢谢。【参考方案3】:

您可以查找对象,然后查找所需的密钥。这适用于任意深度的数据。

function getLongest(object, key) 
    return Object.values(object).reduce((l, v) => 
        if (key in v) return Math.max(l, v[key].length);
        if (v && typeof v === 'object') return Math.max(l, getLongest(v, key));
        return l;    
    , 0);


var data =  array1: [ label: "something1", ref: "option2a" ,  label: "something2", ref: "option2b" ,  label: "something3", ref: "option2a" ,  label: "something4", ref: "option2a" ,  label: "something5", ref: "option2a" ], array2: [ label: "somethinglongest", ref: "option3a" ,  label: "Other", ref: "option3b" ] ;

console.log(getLongest(data, 'label'));

【讨论】:

【参考方案4】:

获取子数组中所有对象的数组。

计算将每个值映射到其长度的值的最大长度:

var obj = 
  "array1": [
      "label": "something1",
      "ref": "option2a"
    ,
    
      "label": "something2",
      "ref": "option2b"
    ,
    
      "label": "something3",
      "ref": "option2a"
    ,
    
      "label": "something4",
      "ref": "option2a"
    ,
    
      "label": "something5",
      "ref": "option2a"
    
  ],
  "array2": [
      "label": "somethinglongest",
      "ref": "option3a"
    ,
    
      "label": "Other",
      "ref": "option3b"
    
  ]
;

console.log(Math.max(...Object.values(obj).flat().map(o => o.label.length)));

【讨论】:

+1 表示flat 方法。你可以不用减少Math.max(...Object.values(obj).flat().map(o => o.label.length)) 希望具有建设性——为什么要在 1 行中执行这么多操作?乍一看或者以后回来调整时,这不是很难理解吗? @CharlieSchliesser 只是因为我打字速度更快并且一次完成。但是任何人都可以提取他想要的所有变量:)【参考方案5】:

另一种选择是遍历obj对象自己的属性,并检查每个标签的长度是否比之前的最长长度长。

var obj = 
  "array1": [
     "label": "something1", "ref": "option2a" ,
     "label": "something2", "ref": "option2b" ,
     "label": "something3", "ref": "option2a" ,
     "label": "something4", "ref": "option2a" ,
     "label": "something5", "ref": "option2a" 
  ], "array2": [ 
     "label": "somethinglongest", "ref": "option3a" ,
     "label": "Other", "ref": "option3b" 
  ]


let longest = 0;

for (key in obj) 
  if(obj.hasOwnProperty(key)) 
    obj[key].forEach(item => 
      if (item.label.length > longest) longest = item.label.length;
    )
  


console.log(longest);

【讨论】:

【参考方案6】: 使用.concat()Object.values() 获取包含所有对象的单个数组。 对包含字符串长度的数组使用.map()。 最后使用.reduce()得到最长字符串的长度。

let data = 
    "array1": [
        "label": "something1", "ref": "option2a",
        "label": "something2", "ref": "option2b",
        "label": "something3", "ref": "option2a",
        "label": "something4", "ref": "option2a",
        "label": "something5", "ref": "option2a"
    ],
    "array2": [
        "label": "somethinglongest", "ref": "option3a",
        "label": "Other", "ref": "option3b"
    ]
;

let reducer = arr => [].concat(...Object.values(arr))
                       .map(( label ) => label.length)
                       .reduce((r, c) => r > c ? r : c);

console.log(reducer(data));

【讨论】:

易读性在这里很有帮助。

以上是关于对象数组的对象。获取具有相同属性的所有值的长度的主要内容,如果未能解决你的问题,请参考以下文章

如何从对象数组中获取具有属性的列表,除非它包含具有特定值的另一个项目?

JavaScript 利用new Set()抽离数组中所有具备相同属性值的对象.

JavaScript 利用new Set()抽离数组中所有具备相同属性值的对象.

LINQ:获取包含具有特定名称和值的属性的数组中的对象

在数组Vue Js中的另一个不同json对象中具有相同值的数组中的所有json对象中添加/合并新项目

数组对象修改某一个属性值的数据类型