基于嵌套值的数组过滤对象数组
Posted
技术标签:
【中文标题】基于嵌套值的数组过滤对象数组【英文标题】:Filtering array of objects with arrays based on nested value 【发布时间】:2016-11-17 10:56:42 【问题描述】:我正在尝试根据一些嵌套对象过滤一个数组。我准备了一些Fiddle
输入数组如下所示:
let arrayOfElements =
[
"name": "a",
"subElements":
[
"surname": 1,
"surname": 2
]
,
"name": "b",
"subElements":
[
"surname": 3,
"surname": 1
]
,
"name": "c",
"subElements":
[
"surname": 2,
"surname": 5
]
];
我希望这种情况下的输出如下所示:
let filteredArray =
[
"name": "a",
"subElements":
[
"surname": 1
]
,
"name": "b",
"subElements":
[
"surname": 1
]
];
我正在使用这个公式来做到这一点:
let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === 1));
输出几乎很好,但它返回的对象包含所有带有姓氏的对象(最好检查一下小提琴:D),而不是把它们剪掉。如何改进过滤?
【问题讨论】:
您是否要根据姓氏进行分组?我的意思是同样的事情应该分组a
和c
,因为他们姓2
。对吗?
【参考方案1】:
这样,您可以在数组中任意深入并过滤任何级别的元素,
arrayOfElements.map((element) =>
return ...element, subElements: element.subElements.filter((subElement) => subElement.surname === 1)
)
Spread operator
将扩展element
,然后过滤subElements
将覆盖subElements
in 元素。
【讨论】:
这应该是答案,因为接受的答案没有产生预期的输出 是的,这个答案更好。写入接受的答案时,对象扩展运算符不存在。 这是修改原始数组 @Aadam 你能分享你的阵列吗? Array.map 不会修改原始数组,而是返回一个具有修改值的新数组。 这个解决方案的问题是返回的元素数量与原来的相同。他们将 subElements 数组为空,因此更正方法是通过检查 subElements 的长度向结果映射添加过滤器。【参考方案2】:调用filter
后,需要将结果通过管道传送到map
,如下所示:
let filteredArray = arrayOfElements
.filter((element) =>
element.subElements.some((subElement) => subElement.surname === 1))
.map(element =>
let newElt = Object.assign(, element); // copies element
return newElt.subElements.filter(subElement => subElement.surname === '1');
);
我在这里假设您不想操纵原始数组。所以,我正在使用 Object.assign。
【讨论】:
这不是只返回子元素数组,而不是过滤后的子数组的完整对象吗? @WannyMiarelli 是正确的。它将返回过滤后的子数组,而不是带有过滤姓氏的完整对象。上面的代码也有错误(字符串检查而不是整数和错字surName)。 这个解决方案没有产生预期的输出:jsbin.com/dunuqeyeje/edit?js,console @LokeshSanapalli,在您最后一次致电filter
时,您需要将surName
更改为surname
。然后它工作。那是我上面的错误。现已更正。
嗨@AndrewEisenberg!感谢您的输入。现在 4 年后,我决定将接受的答案更改为使用扩展运算符的答案,因为它似乎更适合 2020 年 :) 谢谢,我希望没有难过的感觉 :)【参考方案3】:
let filteredArray = arrayOfElements
.filter((element) =>
element.subElements.some((subElement) => subElement.surname === 1))
.map(element =>
let newElt = Object.assign(, element); // copies element
newElt.subElements = newElt.subElements.filter(subElement => subElement.surName === '1');
return newElt;
);
更正确
【讨论】:
【参考方案4】:刚刚改进了上面的答案
let elements =
[
"name": "a",
"subElements":
[
"surname": 1,
"surname": 2
]
,
"name": "b",
"subElements":
[
"surname": 3,
"surname": 1
]
,
"name": "c",
"subElements":
[
"surname": 2,
"surname": 5
]
];
var value = 1;
var filteredArray = elements
.filter(element => element.subElements
.some(subElement => subElement.surname === value)
)
.map(element =>
let n = Object.assign(, element, 'subElements': element.subElements.filter(
subElement => subElement.surname === value
))
return n;
)
console.log(filteredArray)
【讨论】:
【参考方案5】:let filteredArray = arrayOfElements
.filter((element) =>
element.subElements.some((subElement) => subElement.surname == 1))
.map(element =>
return Object.assign(, element, subElements : element.subElements.filter(subElement => subElement.surname == 1));
);
【讨论】:
当您将过滤后的数组与父对象“subElement”合并时,这将给出预期的响应。 这返回了预期的响应【参考方案6】:试试这个解决方案:
data_filter = arrayOfElements.filter(function (element)
return element.subElements.some( function (subElement)
return subElement.surname === surname
);
);
【讨论】:
它不会返回准确的预期响应,而是返回找到的对象中的所有姓氏【参考方案7】:你也可以让它通用:
逻辑
查找所有不同的姓氏并遍历它们 过滤每个对象以检查姓氏是否存在。如果是,请使用Object.assign 复制对象并将subElements
值设置为过滤列表。
创建一个临时数组来保存所有相似的对象并将复制的对象推送到它。
每次迭代不同姓氏时,将此数组推入最终数组。
样本
let arrayOfElements=[name:"a",subElements:[surname:1,surname:2],name:"b",subElements:[surname:3,surname:1],name:"c",subElements:[surname:2,surname:5]];
let distinct_surnames = [];
arrayOfElements.forEach(function(el)
el.subElements.forEach(function(s)
if (distinct_surnames.indexOf(s.surname) < 0) distinct_surnames.push(s.surname)
);
)
let result = [];
distinct_surnames.forEach(function(sn)
let inter = [];
arrayOfElements.forEach(function(el)
let f = el.subElements.filter(function(sub)
return sub.surname === sn;
);
if (f.length > 0)
let _tmp = Object.assign(, el);
_tmp.subElements = f;
inter.push(_tmp);
);
result.push(inter);
)
console.log(result)
注意:箭头函数用于保持this
的引用。如果你没有在函数内部使用this
,你也可以使用普通函数。
【讨论】:
【参考方案8】:function display_message()
let arrayOfElements = [
"name": "a",
"subElements": [
"surname": 1
,
"surname": 2
]
,
"name": "b",
"subElements": [
"surname": 3
,
"surname": 1
]
,
"name": "c",
"subElements": [
"surname": 2
,
"surname": 5
]
];
// console.log(arrayOfElements);
var surname = 1;
let filteredArray = arrayOfElements.filter((element) => element.subElements.some((subElement) => subElement.surname === surname));
for(var data in filteredArray)
filteredArray[data].subElements = "surname": surname;
console.log(filteredArray);
<input type="button" onclick="display_message();" value="click"/>
【讨论】:
以上是关于基于嵌套值的数组过滤对象数组的主要内容,如果未能解决你的问题,请参考以下文章