从对象数组中获取唯一元素数组
Get array of unique elements from arrays of objects
我有如下数组:
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}
];
我正在尝试使用 Underscore 获取包含唯一元素的合并数组,但它不起作用。这是我的代码:
function getAllFiles(alldocs) {
var all = [];
_.each(alldocs, function(element) {
all = _.union(all, element.files);
});
return all;
}
但是我得到一个包含重复项的数组。
普通 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>');
使用lodash,可以使用_.uniqBy
result = _.uniqBy(result, function (e) {
return e.name;
});
这是因为你使用的是对象数组,underscore 在比较项目时不知道使用哪个对象属性(例如名称,其他),
这是一个干净的解决方案:
files = _.chain(files).indexBy("name").values();
使用下划线你可以这样做:
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
工作代码here
您需要在 union
调用后应用 uniq
方法。
问题是 uniq
默认情况下使用 ===
运算符来测试数组元素是否相等。因此,如果您有对象数组,每个对象将通过 reference 而不是值进行比较,这显然是不希望出现的行为。这个问题可以通过提供 uniq
和额外的参数 - 回调函数 (iteratee
) 来解决,它将数组元素转换为简单的可比较值。在您的情况下,您可以使用 JSON.stringify
方法,该方法 returns 对象的字符串表示形式。
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);
我有如下数组:
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}
];
我正在尝试使用 Underscore 获取包含唯一元素的合并数组,但它不起作用。这是我的代码:
function getAllFiles(alldocs) {
var all = [];
_.each(alldocs, function(element) {
all = _.union(all, element.files);
});
return all;
}
但是我得到一个包含重复项的数组。
普通 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>');
使用lodash,可以使用_.uniqBy
result = _.uniqBy(result, function (e) {
return e.name;
});
这是因为你使用的是对象数组,underscore 在比较项目时不知道使用哪个对象属性(例如名称,其他), 这是一个干净的解决方案:
files = _.chain(files).indexBy("name").values();
使用下划线你可以这样做:
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
工作代码here
您需要在 union
调用后应用 uniq
方法。
问题是 uniq
默认情况下使用 ===
运算符来测试数组元素是否相等。因此,如果您有对象数组,每个对象将通过 reference 而不是值进行比较,这显然是不希望出现的行为。这个问题可以通过提供 uniq
和额外的参数 - 回调函数 (iteratee
) 来解决,它将数组元素转换为简单的可比较值。在您的情况下,您可以使用 JSON.stringify
方法,该方法 returns 对象的字符串表示形式。
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);