Get unique values from array of objects

问题: I have an array of dynamic objects like that: var arr = [ {state: "FL"}, {state: "NY"}, {state: "FL"}, {gender: "Male"}, {state: "NY"}, {gender: "...

问题:

I have an array of dynamic objects like that:

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

How can I get just the unique objects?

The desired output is an array containing just the unique objects:

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

I'm trying something like that using reduce, but on this way I need know the object key:

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

It's not a duplicate because the other questions does not use "dynamic object" to get unique


回答1:

You could stringify all objects, get the unique JSON and convert the strings back to objects.

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

If you have more than one key in the object and because if you have object where the keys are in different order, I suggest to get the entries first, sort this array, stringify it for a set and get new objects back.

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


回答2:

You can reduce to an object where each value in your objects is a key in this one (as objects can't double up on keys - thus allowing you to get unique values), and then use that with Object.values to get the values within your reduced object like so:

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

res = Object.values(reducedObj);
console.log(res);


回答3:

quick way which comes to my mind given the simplicity of given objects

  1. convert all objects to string using JSON.stringify
  2. get all unique values by converting that array of string to set
  3. convert strings again to objects

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


回答4:

This should work

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];
  }
}, []);


回答5:

I know, I know, me too... but my answer's a bit more succinct.

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

This has the usual caveats with using JSON.stringify, namely that according to spec, you can't rely on the order of keys to be consistent. If you only have a single key, this will never be a problem. It also likely won't be a problem if every object is constructed by adding keys in the same order, as most implementations will preserve key-added order.


回答6:

A lot of ways to do this: here are two:

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


回答7:

Using filter method :

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

  • 发表于 2019-03-01 19:00
  • 阅读 ( 187 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除