如何过滤对象数组并根据特定属性变得不同
Posted
技术标签:
【中文标题】如何过滤对象数组并根据特定属性变得不同【英文标题】:How to filter array of objects and get distinct based on a specific property 【发布时间】:2021-09-02 22:45:48 【问题描述】:我有以下数组,我想根据一个属性进行过滤,并与另一个属性区分开来。我设法让它工作,但有没有更清洁的方法来实现这一点?
var result = [
"Class": "Class C",
"Group": "Group A",
"Value": 1
,
"Class": "Class C",
"Group": "Group A",
"Value": 2
,
"Class": "Class A",
"Group": "Group B",
"Value": 2
,
"Class": "Class C",
"Group": "Group B",
"Value": 10
];
result = result.reduce((x,
Class,
Group,
Value
) =>
Class.includes("Class C") && x.push(
Class,
Group,
Value
);
return x;
, []);
console.log(result);
result = [...new Map(result.map(item => [item["Group"], item])).values()];
console.log("Expected Result:");
console.log(result);
【问题讨论】:
【参考方案1】:您有两个任务,过滤和查找不同的项目(实际上是:分组)。
所以当我们定义两个函数时,一个用于通过给定属性进行过滤:
const filterByProp =
(prop) =>
(value) =>
(items) =>
items.filter((item) => item[prop] === value);
还有一个用于通过给定属性查找不同的(在这种情况下:每个值的每个第一项):
const distinctByProp =
(prop) =>
(items) =>
Object.values(items.reduce((group, item) =>
if (!group.hasOwnProperty(item[prop])) group[item[prop]] = item;
return group;
, ));
我们可以的
const onlyClassC = filterByProp("Class")("Class C");
const distinctByGroup = distinctByProp("Group");
const filtered = distinctByGroup(onlyClassC(result));
并获得filtered
为:
[
"Class": "Class C",
"Group": "Group A",
"Value": 1
,
"Class": "Class C",
"Group": "Group B",
"Value": 10
]
如果您想要每个不同组的最后一项而不是第一项,请从 distinctByProp
中删除 if (!group.hasOwnProperty(item[prop]))
。
const filterByProp =
(prop) =>
(value) =>
(items) =>
items.filter((item) => item[prop] === value);
const distinctByProp =
(prop) =>
(items) =>
Object.values(items.reduce((group, item) =>
if (!group.hasOwnProperty(item[prop])) group[item[prop]] = item;
return group;
, ));
// -----------------------------------------------------------------------
const onlyClassC = filterByProp("Class")("Class C");
const distinctByGroup = distinctByProp("Group");
// -----------------------------------------------------------------------
var result = [
"Class": "Class C",
"Group": "Group A",
"Value": 1
,
"Class": "Class C",
"Group": "Group A",
"Value": 2
,
"Class": "Class A",
"Group": "Group B",
"Value": 2
,
"Class": "Class C",
"Group": "Group B",
"Value": 10
];
const filtered = distinctByGroup(onlyClassC(result));
console.log(filtered);
【讨论】:
是的,这样就行了!谢谢。 @nadz 有许多库提供了我自己在这里编写的两个辅助函数等,因此您只需要实现“我们可以做”块。他们中的一些人更倾向于“函数式编程”,一些人采用更传统的方法,看看周围 - 重新发明***并不总是值得的。 是的,我同意。我会做一些挖掘工作。非常感谢! @nadz,即使预期的输出与您的建议不同,您为什么还要接受这个答案?只是好奇。 通过我上面采用的更多“函数式编程”方法,您可以获得更高的函数可重用性和可组合性,即您可以创建一个函数filterByClass = filterByProp("Class")
,并保留它,并将其专门用于过滤器仅在需要时才设置值,或者您可以使用它在其他地方进行过滤。【参考方案2】:
这不是最有效的方法,只是更简洁的代码。
const result = [
Class: "Class C", Group: "Group A", Value: 1 ,
Class: "Class C", Group: "Group A", Value: 2 ,
Class: "Class A", Group: "Group B", Value: 2 ,
Class: "Class C", Group: "Group B", Value: 10 ,
];
const output = result
.filter(obj => obj.Class.includes("Class C"))
.reverse()
.filter(
(obj, i, arr) => i === arr.findIndex(obj2 => obj.Group === obj2.Group)
)
.reverse();
console.log(output);
【讨论】:
【参考方案3】:我认为这不一定比你的更好,但它采用了几种不同的方法。即先对数据进行排序,这样您就不必查询找到最大值并首先过滤以摆脱欺骗。
let classFilter = "Class C", filtered =
// We're making an object that should be delivered as an array
Object.values(result
// first sort by value so when we filter, we capture the highest if there are duplicates
.sort((a, b) => (a.Value < b.Value) ? 1 : -1)
// filter out any duplicates of our target classFilter
.filter(e => e.Class === classFilter)
// get unique only Groups
.reduce((b, a) =>
if (!b.hasOwnProperty(a.Group)) b[a.Group] = a;
return b;
, )
)
let result = [
"Class": "Class C",
"Group": "Group A",
"Value": 1
,
"Class": "Class C",
"Group": "Group A",
"Value": 2
,
"Class": "Class A",
"Group": "Group B",
"Value": 2
,
"Class": "Class C",
"Group": "Group B",
"Value": 10
];
let classFilter = "Class C"
let filtered = Object.values(result.sort((a, b) => (a.Value < b.Value) ? 1 : -1).filter(e => e.Class === classFilter).reduce((b, a) =>
if (!b.hasOwnProperty(a.Group)) b[a.Group] = a;
return b;
, ))
console.log(filtered)
【讨论】:
以上是关于如何过滤对象数组并根据特定属性变得不同的主要内容,如果未能解决你的问题,请参考以下文章