[英]Get array of unique elements from arrays of objects
i have arrays like the following ones: 我有如下数组:
files = [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Bar', other: true}
];
files = [
{name: 'Lorem', other: true},
{name: 'Xxxxx', other: true}
];
files = [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Epic', other: true},
{name: 'Xxxxx', other: true}
];
I'm trying to get a merged array with unique elements with Underscore, but it doesn't work. 我正在尝试使用Underscore获取具有唯一元素的合并数组,但是它不起作用。 Here is my code:
这是我的代码:
function getAllFiles(alldocs) {
var all = [];
_.each(alldocs, function(element) {
all = _.union(all, element.files);
});
return all;
}
But i get an array with duplicate items. 但是我得到一个重复项的数组。
Using underscore you can do it like this: 使用下划线,您可以这样做:
files1 = [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Bar', other: true}
];
files2 = [
{name: 'Lorem', other: true},
{name: 'Xxxxx', other: true}
];
files3 = [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Epic', other: true},
{name: 'Xxxxx', other: true}
];
//append all json
all = _.union(files1,files2, files3);
//get unique by define function which returns name (deciding factor for unique)
all = _.uniq(all, function(d){return d.name});
console.log(all);//prints the unique elements
A solution in plain Javascrift a temporary object and Array#forEach()
用简单的Javascrift临时对象和
Array#forEach()
解决方案
var files1 = [{ name: 'Lorem', other: true }, { name: 'Foo', other: true }, { name: 'Bar', other: true }], files2 = [{ name: 'Lorem', other: true }, { name: 'Xxxxx', other: true }], result = function (array) { var o = {}, r = []; array.forEach(function (a) { if (!(a.name in o)) { o[a.name] = a; r.push(o[a.name]); } }); return r; }(files1.concat(files2)); document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You need to apply uniq
method after union
call. union
调用之后,您需要应用uniq
方法。
The problem is that uniq
by default uses ===
operator to test array element equality. 问题是
uniq
默认情况下使用===
运算符来测试数组元素的相等性。 So if you have array of objects, each object will be compared by reference , not value, which is obviously undesired behaviour. 因此,如果您有对象数组,则将通过引用而不是值来比较每个对象,这显然是不希望有的行为。 This problem can be solved by supplying
uniq
with extra parameter - callback function ( iteratee
) which will convert array element to simply comparable value. 通过为
uniq
提供额外的参数-回调函数( iteratee
)可以解决此问题,该函数会将数组元素转换为简单的可比较值。 In your case you can use JSON.stringify
method which returns string representation of an object. 您可以使用
JSON.stringify
方法,该方法返回对象的字符串表示形式。
function getAllFiles(alldocs) {
var union = _.union.apply(null, alldocs.map(function(v) {
return v.files;
}));
return _.uniq(union, function(v) {
return JSON.stringify(v);
});
}
var alldocs = [
{files: [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Bar', other: true}
]},
{files: [
{name: 'Lorem', other: true},
{name: 'Xxxxx', other: true}
]},
{files: [
{name: 'Lorem', other: true},
{name: 'Foo', other: true},
{name: 'Epic', other: true},
{name: 'Xxxxx', other: true}
]}
];
var result = getAllFiles(alldocs);
Using lodash, you can use _.uniqBy
使用lodash,可以使用
_.uniqBy
result = _.uniqBy(result, function (e) {
return e.name;
});
https://jsfiddle.net/mw230kea/1/ https://jsfiddle.net/mw230kea/1/
这是因为您使用的是对象数组,而下划线在比较项目 (例如名称,其他) 时不知道要使用哪个对象属性 ,这是一个干净的解决方案:
files = _.chain(files).indexBy("name").values();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.