繁体   English   中英

从对象数组中获取唯一值

[英]Get unique values from array of objects

我有一个像这样的动态对象数组:

var arr = [
    {state: "FL"},
    {state: "NY"},
    {state: "FL"},
    {gender: "Male"},
    {state: "NY"},
    {gender: "Female"},
    {gender: "Female"},
    {year: "1990"}
]

我怎样才能获得独特的物体?

所需的输出是一个只包含唯一对象的数组:

arr = [
    {state: "FL"},
    {state: "NY"},
    {gender: "Male"},
    {gender: "Female"},
    {year: "1990"}
]

我正在尝试使用reduce这样的东西,但在这种方式我需要知道对象键:

arr = arr.reduce((acc, curr) => 
    acc.find(e => e['state'] === curr['state']) ? acc : [...acc, curr], [])

这不是重复,因为其他问题不使用“动态对象”来获得独特性

您可以对所有对象进行字符串化,获取唯一的JSON,然后将字符串转换回对象。

 var array = [{ state: "FL" }, { state: "NY" }, { state: "FL" }, { gender: "Male" }, { state: "NY" }, { gender: "Female" }, { gender: "Female" }, { year: "1990" }], unique = Array.from( new Set(array.map(o => JSON.stringify(o))), s => JSON.parse(s) ); console.log(unique); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

如果对象中有多个键,并且因为如果对象的键不同,我建议您首先获取条目,对此数组进行排序,将其字符串化为一个集合,然后将新对象返回。

 var array = [{ foo: 42, state: "FL" }, { state: "FL", foo: 42 }, { state: "FL" }, { state: "NY" }, { state: "FL" }, { gender: "Male" }, { state: "NY" }, { gender: "Female" }, { gender: "Female" }, { year: "1990" }], unique = Array.from( new Set(array.map(o => JSON.stringify(Object.entries(o).sort(([a], [b]) => a.localeCompare(b))))), s => Object.assign({}, ...JSON.parse(s).map(([k, v]) => ({ [k]: v }))) ); console.log(unique); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

您可以reduce为一个对象,其中对象中的每个值都是该对象中的键(因为对象不能在键上加倍 - 从而允许您获取唯一值),然后将其与Object.values一起使用以获取值在缩小的对象中,如下所示:

 const arr = [{state: "FL"},{state: "NY"},{state: "FL"},{gender: "Male"},{state: "NY"},{gender: "Female"},{gender: "Female"},{year: "1990"}] const res = Object.values(arr.reduce((acc, obj) => { const [[key, val]] = Object.entries(obj); return (acc[val] = {[key]: val}, acc); }, {})); console.log(res); 

鉴于给定对象的简单性,我想到了快速的方法

  1. 使用JSON.stringify将所有对象转换为字符串
  2. 通过转换要set的字符串数组来获取所有唯一值
  3. 再次将字符串转换为对象

 var arr = [{state: "FL"},{state: "NY"},{state: "FL"},{gender: "Male"},{state: "NY"},{gender: "Female"}, {gender: "Female"},{year: "1990"} ] const stringArr = arr.map(str => JSON.stringify(str)); const uniqueStrs = [ ...new Set(stringArr)] // removes duplicates const result = uniqueStrs.map(str => JSON.parse(str)); console.log(result); 

我知道,我知道,我也是......但我的回答更简洁一些。

[...new Set(arr.map(JSON.stringify))].map(JSON.parse);

这有使用JSON.stringify的常见警告,即根据规范,您不能依赖键的顺序是一致的。 如果您只有一个密钥,这将永远不会成为问题。 如果通过以相同顺序添加键来构造每个对象,也可能不会成为问题,因为大多数实现将保留键添加顺序。

这个性能比使用JSON.parse和stringify的任何东西要好得多。

 var arr = [ {state: "FL"}, {state: "NY"}, {state: "FL"}, {gender: "Male"}, {state: "NY"}, {gender: "Female"}, {gender: "Female"}, {year: "1990"} ]; const unique = arr => arr.filter((item, index) => !arr.some((i, idx) => idx > index && Object.getOwnPropertyNames(item).every(property => i[property] === item[property]))); console.log(unique(arr)); 

或者像你正在尝试的那样使用reduce而不是filter

 var arr = [ {state: "FL"}, {state: "NY"}, {state: "FL"}, {gender: "Male"}, {state: "NY"}, {gender: "Female"}, {gender: "Female"}, {year: "1990"} ]; const unique = arr => arr.reduce((results, item) => { if (!results.some(i => Object.getOwnPropertyNames(item).every(property => i[property] === item[property]))) { results.push(item); } return results; }, []); console.log(unique(arr)); 

这应该工作

 const arr = [ { state: 'FL' }, { state: 'NY' }, { state: 'FL' }, { gender: 'Male' }, { state: 'NY' }, { gender: 'Female' }, { gender: 'Female' }, { year: '1990' }, ]; arr.reduce((array, obj) => { for (const target of array) { if (JSON.stringify(target) === JSON.stringify(obj)) { return array; } return [...array, obj]; } }, []); 

有很多方法可以做到这一点:这里有两个:

  1. reduce
  2. for loop

 var arr = [ {state: "FL"}, {state: "NY"}, {state: "FL"}, {gender: "Male"}, {state: "NY"}, {gender: "Female"}, {gender: "Female"}, {year: "1990"} ] //two solutions //1. reduce and some let arr1 = arr.reduce( (acc, currentValue) => { const key = Object.keys(currentValue)[0]; //we only have one property! const inArr = acc.some((element) => {return element[key] == currentValue[key]}); if (!inArr) { acc.push(currentValue); } return acc; },[]); console.log(arr1); //2. for loop //you can still do a for loop (Quick): const shadow = []; const iMax= arr.length; for (let i = 0; i < iMax; i++) { const key = Object.keys(arr[i])[0]; //we only have one property! //check if value is not in shadow array if (shadow.indexOf(arr[i][key]) == -1) { arr.push(arr[i]); shadow.push(arr[i][key]); } } //splice off the original values arr.splice(0, iMax); console.log(arr); 

使用filter方法:

 var arr = [ {state: "FL"}, {state: "NY"}, {state: "FL"}, {gender: "Male"}, {state: "NY"}, {gender: "Female"}, {gender: "Female"}, {year: "1990"} ] var len = arr.length ; var result = [] ; var result = arr.filter( (cur, inx) => { var same = 0 ; var curKey = Object.keys(cur)[0] ; for ( var i = inx + 1; i < len; i++ ) if ( cur[curKey] === arr[i][curKey] ) { same++; break; } return !same; }) console.log( result ) ; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM