Javascript过滤对象内的数组

Posted

技术标签:

【中文标题】Javascript过滤对象内的数组【英文标题】:Javascript filter arrays within an object 【发布时间】:2020-10-21 11:39:33 【问题描述】:

假设我有一个具有结构的对象

data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]

我想提取 key2 == "abc" 所在的元素。

预期输出:

data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc"],
    b : [values: key1: 7, key2: "abc"]

我尝试关注类似的examples,但未能实现我想要的。

【问题讨论】:

【参考方案1】:

使用Object.entries()data 的所有键/值对提取为一个数组,map 在每对上,然后在每个值上使用filter 以提取您想要的。

然后您可以使用 Object.fromEntries() 重新加入它

const data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]


const findKey = 'key2'
const findValue = 'abc'

const newData = Object.fromEntries(Object.entries(data).map(([ key, val ]) =>
  [ key, val.filter(( values ) => values?.[findKey] === findValue) ]))
  
console.log(newData)

如果你还没有看到Optional Chaining,这个...

values?.[findKey] === findValue

等价于

!!values && values[findKey] === findValue

【讨论】:

我的大脑很痛,试图跟随那里发生的所有解构。 虽然这行得通,但这里有太多的解构,你可能会失去流程 @ManosKounelakis 这里只有两个解构,一个数组 ([ key, val ]) 和一个对象 ( value )。不确定你认为什么太多? 你真的需要可选链吗?我想如果您尝试访问不存在的第一层的属性,它会返回未定义? @Ifaruki 以防任何数组条目没有 values 属性。如果他们这样做了,values 将是 undefinedvalues[findKey] 会抛出一个错误【参考方案2】:

简单的 for of 循环遍历键和 filters 数组并直接重新分配属性。 直接改变数据。

使用filter 和destructures key2 对其进行过滤。

const data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]


for(const k of Object.keys(data))
  data[k] = data[k].filter((values: key2)=>key2==='abc')
  
console.log(data)

添加了对 .length 的检查以修剪具有空数组的键, 并为 key2 设置默认值,因此 values 属性是可选的:

const data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]


for(const k of Object.keys(data))
  (data[k] = data[k].filter((values:key2=)=>key2==='abc'))
    .length || delete data[k]
  
console.log(data)

【讨论】:

【参考方案3】:
data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]


var resp = 
for (var key in data)
    var local = [];
    data[key].forEach(element => 
        if(element['values']['key2'] == 'abc')
            local.push(element);
        
    )
    resp[key] = local;

console.log(resp);

回应

a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc"],
b : [values: key1: 7, key2: "abc"]

【讨论】:

【参考方案4】:

您可以将对象的属性简化为通过过滤器的属性

const data = 
    a : [values: key1: 5, key2: "abc", values: key1: 3, key2: "abc", values: key1: 4, key2: "cde"],
    b : [values: key1: 3, key2: "ffe", values: key1: 11, key2: "gga", values: key1: 7, key2: "abc"]
;

const results = Object.getOwnPropertyNames(data).reduce((results, key) => 
  const filtered = data[key].filter(item => item.values.key2 === 'abc');
  if (filtered && filtered.length) 
    results[key] = filtered;
  
  return results;
, );

console.log(results);

【讨论】:

如果他们想要省略空结果,可能需要与 OP 澄清,但这是一个很好的补充【参考方案5】:

由于您需要迭代对象属性,我建议您使用Object.keys(object) 提取它们,您可以在此处找到:

https://developer.mozilla.org/es/docs/Web/javascript/Referencia/Objetos_globales/Object/keys

我建议你这样迭代:

Object.keys(data).forEach(attribute => 
        data[attribute] = data[attribute].filter(value => value.values.key2 === 'abc');
)

祝你好运。

【讨论】:

以上是关于Javascript过滤对象内的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何通过猫鼬(javascript)中的多个值查询数组内的对象?

数组内的角度过滤器数组

如何在Javascript中选择对象内的数组内的字段[重复]

数组 - Javascript - 使用输入搜索过滤对象数组

基于多值对象过滤javascript对象数组

如何在javascript中将对象数组过滤为另一个对象数组? [关闭]