Получить уникальные значения из массива объектов - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть такой массив динамических объектов:

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

Это не дубликат, потому что другие вопросы не используют "динамический объект ", чтобы получить уникальный

Ответы [ 8 ]

0 голосов
/ 12 марта 2019

Это выполнение будет намного лучше, чем что-либо другое с использованием 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));

или с уменьшением вместо фильтра, как вы пытались

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));
0 голосов
/ 28 февраля 2019

Я знаю, я знаю, я тоже ... но мой ответ немного более лаконичен.

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

Это обычные предостережения с использованием JSON.stringify, а именно то, что согласно спецификации вы можетене полагайтесь на последовательность ключей, чтобы быть последовательными.Если у вас есть только один ключ, это никогда не будет проблемой.Это также, вероятно, не будет проблемой, если каждый объект создается путем добавления ключей в том же порядке, так как большинство реализаций сохранит порядок добавления ключей.

0 голосов
/ 28 февраля 2019

Используя 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 ) ;
0 голосов
/ 28 февраля 2019

Есть много способов сделать это: вот два:

  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);
0 голосов
/ 28 февраля 2019

Это должно работать

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];
  }
}, []);
0 голосов
/ 28 февраля 2019

Вы можете 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);
0 голосов
/ 28 февраля 2019

быстрый способ, который приходит мне в голову, учитывая простоту заданных объектов

  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);
0 голосов
/ 28 февраля 2019

Вы можете привести в порядок все объекты, получить уникальный 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; }
...