【问题标题】:Javascript loop trough array of object and return one object containing only keys that have their values changedJavascript 循环遍历对象数组并返回一个对象,该对象仅包含其值已更改的键
【发布时间】:2019-10-21 06:56:48
【问题描述】:

我有一个需要循环的对象数组,并检查对象的键是否具有不同的值。如果是,则返回此密钥。

const arrayOfObjects = [
  { item: { first_name: "Joe", last_name: "Dow", age: 15 } },
  { item: { first_name: "Joe", last_name: "d", age: 15 } },
  { item: { first_name: "Joe", last_name: "Dow", age: 20 } }
];

预期的结果应该是

const result = {
  last_name: true,
  age: true
}

PS:每个对象总是有相同数量的键

【问题讨论】:

  • “有不同的价值”比什么?
  • 对不起,我的解释能力很差,在第二个对象中last_name已经改变,所以需要标记并返回如果key改变了它需要返回,不管多少次跨度>
  • 获取数组第一项的值,做一个 foreach 和一个 if 来与所有其他项的值进行比较,如果其中一个不匹配,则将结果设置为 true/false 并打破foreach.
  • 所以您正在寻找数组中“last_name”属性与数组中第一个条目的值不同的任何条目?
  • 那么,您只想查看每个对象中item 属性下的键值吗?换句话说,如果数组中有像{ item: { first_name: "Joe", last_name: "Dow", age: 15 }, foo: "bar" } 这样的元素会发生什么?

标签: javascript arrays object filter key


【解决方案1】:

您可以循环访问arrayOfObjects。检查当前item 的键与之前对象的item 相比是否具有不同的值。如果是,则将该键设置为true in result

const arrayOfObjects = [{ item: { first_name: "Joe", last_name: "Dow", age: 15 } }, { item: { first_name: "Joe", last_name: "d", age: 15 } }, { item: { first_name: "Joe", last_name: "Dow", age: 20 } }];
const result = {};

arrayOfObjects.forEach(({ item }, i, arr) => {
  if (i === 0) return; // skip the first item
  
  const prev = arr[i - 1].item; // get the previous item
  for (const key in item) {
    if (item[key] !== prev[key])
      result[key] = true
  }
})

console.log(result)

【讨论】:

  • 如果所有值都必须相同,那么从第一个项目中选择值与每个人进行比较而不是获取前一个项目不是更好的性能吗?
  • 这是否适用于不相邻的差异?
  • @ggorlen 我没明白你的意思
  • @ggorlen 差异不会影响结果,因为这遵循从第一个到最后一个项目的方法,这意味着您不能有不同的模式,例如 [1, 1] 变成 [2, 2] , 在执行的某个地方会有一个 [1, 2] 比较,将 key 设置为 true。
  • 你假设 OP 想要与前一个不同,而不是第一个。
【解决方案2】:

只需使用find。更清楚了

const data = [
    { item: { first_name: "Joe", last_name: "Dow", age: 15 } },
    { item: { first_name: "Joe", last_name: "d", age: 15 } },
    { item: { first_name: "Joe", last_name: "Dow", age: 20 } }
];

let result = {};

for (var key in data[0].item) {
  if (data.find((el) => el.item[key] !== data[0].item[key])) {
    result[key] = true;
  }
}
console.log(result);

【讨论】:

  • @adiga find 应该比一些快一点?只是好奇
  • find 获取匹配条件的对象,而some 返回一个布尔值
【解决方案3】:

您可以检查一下嵌套对象。

function check(source, target, result) {
    Object.entries(source).forEach(([k, v]) => {
        if (v && typeof v === 'object') return check(v, target[k], result);
        if (result[k] === undefined) result[k] = true;
        result[k] = result[k] && v === target[k];
    });
    return result;
}

var arrayOfObjects = [{ item: { first_name: "Joe", last_name: "Dow", age: 15 } }, { item: { first_name: "Joe", last_name: "d", age: 15 } }, { item: { first_name: "Joe", last_name: "Dow", age: 20 } }],
    result = arrayOfObjects.reduce((r, o, _, [q]) => check(q, o, r), {});

console.log(result);

【讨论】:

    【解决方案4】:

    您还可以使用Array.reduceSet 解决此问题,您可以在其中对键进行分组并继续添加值。然后过滤集合的大小...如果大于 1,则您有多个值:

    const data = [ { item: { first_name: "Joe", last_name: "Dow", age: 15 } }, { item: { first_name: "Joe", last_name: "d", age: 15 } }, { item: { first_name: "Joe", last_name: "Dow", age: 20 } } ];
    
    let result = data.reduce((r,{item},i,a) => {
     Object.keys(item).forEach(k => r[k] = (r[k] || new Set()).add(item[k]))	
     return i == (a.length-1) 
     ? Object.keys(r).filter(k => r[k].size > 1).reduce((r,k) => (r[k] = true, r), {})
     : r
    }, {})
    
    console.log(result)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      • 2021-12-16
      • 2010-12-07
      • 2019-10-13
      相关资源
      最近更新 更多