Javascript 从对象数组中获取唯一元素数组

Javascript 从对象数组中获取唯一元素数组,javascript,arrays,underscore.js,unique,union,Javascript,Arrays,Underscore.js,Unique,Union,我有如下数组: files = [ {name: 'Lorem', other: true}, {name: 'Foo', other: true}, {name: 'Bar', other: true} ]; files = [ {name: 'Lorem', other: true}, {name: 'Xxxxx', other: true} ]; files = [ {nam

我有如下数组:

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}
      ];
我试图得到一个带有下划线的唯一元素的合并数组,但它不起作用。这是我的密码:

function getAllFiles(alldocs) {
  var all = [];

  _.each(alldocs, function(element) {
    all = _.union(all, element.files);
  });

  return all;
}

但是我得到了一个包含重复项的数组。

纯Java的解决方案使用临时对象和

var files1=[{name:'Lorem',other:true},{name:'Foo',other:true},{name:'Bar',other:true}],
files2=[{name:'Lorem',other:true},{name:'Xxxxx',other:true}],
结果=函数(数组){
变量o={},r=[];
array.forEach(函数(a){
如果(!(o中的a.名称)){
o[a.name]=a;
r、 推(o[a.name]);
}
});
返回r;
}(files1.concat(files2));

document.write(“”+JSON.stringify(结果,0,4)+“”)纯Javascrift中的解决方案临时对象和

var files1=[{name:'Lorem',other:true},{name:'Foo',other:true},{name:'Bar',other:true}],
files2=[{name:'Lorem',other:true},{name:'Xxxxx',other:true}],
结果=函数(数组){
变量o={},r=[];
array.forEach(函数(a){
如果(!(o中的a.名称)){
o[a.name]=a;
r、 推(o[a.name]);
}
});
返回r;
}(files1.concat(files2));

document.write(“”+JSON.stringify(结果,0,4)+“”)使用lodash,您可以使用
\uqby

   files =  _.chain(files).indexBy("name").values();

使用lodash,您可以使用
\uqby

   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

这是因为您使用的是对象数组,下划线不知道在比较项目时使用哪个对象属性(例如名称、其他), 以下是一个干净的解决方案:

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

使用下划线可以执行以下操作:

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);

工作代码

使用下划线可以如下操作:

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);
工作代码

您需要在调用
union
后应用方法

问题是
uniq
默认情况下使用
=
操作符来测试数组元素的相等性。因此,如果您有一个对象数组,那么每个对象都将按引用进行比较,而不是按值进行比较,这显然是不希望的行为。这个问题可以通过向uniq提供额外的参数回调函数(
iteratee
)来解决,该函数将数组元素转换为简单的可比较值。在您的例子中,可以使用
JSON.stringify
方法返回对象的字符串表示形式

您需要在调用
union
后应用方法

问题是
uniq
默认情况下使用
=
操作符来测试数组元素的相等性。因此,如果您有一个对象数组,那么每个对象都将按引用进行比较,而不是按值进行比较,这显然是不希望的行为。这个问题可以通过向uniq提供额外的参数回调函数(
iteratee
)来解决,该函数将数组元素转换为简单的可比较值。在您的例子中,可以使用
JSON.stringify
方法返回对象的字符串表示形式


请看,您可能还可以将下面给出的解决方案与
union一起使用,它们都只检查“name”属性,但您可能希望区分“name”和“other”属性。在阵列上循环并检查两个。如果只是要检查的单个值,则可以使用映射并减少一行。请参阅,您可能还可以使用
union
下面给出的解决方案仅检查“name”属性,但您可能希望区分“name”和“other”属性。在阵列上循环并检查两个。如果只是要检查的单个值,可以使用贴图并减少一条直线。