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

У меня есть массив объектов, который выглядит следующим образом:

[
  {
    "places": "NEW YORK",
    "locations": "USA"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  }
]

Я хочу фильтровать и получать только уникальные записи.Я попробовал следующую функцию, но она не работает:

function onlyUnique(value, index, self) { 
  return self.indexOf(value) === index;
}

Использование Set, похоже, тоже не работает.Есть идеи?

Ответы [ 6 ]

2 голосов
/ 04 апреля 2019

Простое решение с использованием new Set().

const data = [
            {
                "places": "NEW YORK",
                "locations": "USA"
            },
            {
                "places": "MONTREAL",
                "locations": "QUEBEC",
                "country": "Canada"
            },
  {
                "places": "MONTREAL",
                "locations": "QUEBEC",
                "country": "Canada"
            },

        ];
        
const uniqueArray = a => [...new Set(a.map(o => JSON.stringify(o)))].map(s => JSON.parse(s));

console.log(uniqueArray(data)); 
0 голосов
/ 04 апреля 2019

Если ваши значения ключа просты, как в вашем примере, то вы можете сделать что-то вроде следующего для обработки случаев, когда объекты в вашем массиве имеют одинаковые ключи и значения, но не в том же порядке (так как порядок свойств объектане гарантируется во всех браузерах ).

  • Преобразование объектов в массивы с использованием Object.entries, сортировка и преобразование в строки с помощью JSON.stringify
  • Удаление дубликатов с помощью Setи преобразовать строки обратно в массивы, используя JSON.parse, а затем в объекты, используя reduce, чтобы преобразовать пары массивов в пары значений ключей объекта

const arr = [{
    "places": "NEW YORK",
    "locations": "USA"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },
  {
    "country": "Canada",
    "places": "MONTREAL",
    "locations": "QUEBEC"
  }
];

let strings = arr.map(obj => JSON.stringify(Object.entries(obj).sort()));

let result = [...new Set(strings)].map((s) => {
  return JSON.parse(s).reduce((acc, [k, v]) => {
    acc[k] = v;
    return acc;
  }, {});
});

console.log(result);
// [{"locations":"USA","places":"NEW YORK"},{"country":"Canada","locations":"QUEBEC","places":"MONTREAL"}]
0 голосов
/ 04 апреля 2019

Примерно так:

 var distObj = {};
 for(let i = 0; i < obj.places.lenght; i++){
    let tmp = obj.places;
    distObj[i].places = obj[i].places.filter(item => item !== tmp);
 }

Если вы комбинируете это с for (k в Obj) и обратным вызовом, вы можете перебирать все глубины и атрибуты в Object

0 голосов
/ 04 апреля 2019

Решение:

Вы можете использовать filter с локальным Set объектом.Сравнивая строковые объекты и свойство size до и после попытки добавления к Set, вы можете вернуть уникальный массив, спросив, не совпадают ли два числа.


Код:

place_array.filter(v => b.size != b.add(JSON.stringify(v)).size, b = new Set());

Зачем использовать этот код?

В отличие от многих других ответов, он опирается на единственный проход через массив с помощьюитератор фильтра.Это означает, что он более производительный, чем несколько циклов в массиве.Он также использует только локализованные переменные, что означает, что они не являются глобальным беспорядком и, поскольку метод filter является функциональным, абсолютно никаких побочных эффектов.

Примечание: Всегда естьснижение производительности при использовании объекта Set в любой ситуации. Это сводится к внутренним элементам браузера, однако при нахождении уникальных объектов / массивов stringify в методе Set, вероятно, лучшее решение.Хотя с невероятно маленькими наборами данных вы можете найти практичным использование массива или создание собственного объекта для конкретной задачи.

Рабочий пример:

let place_array = [{
    "places": "NEW YORK",
    "locations": "USA"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },

];

let result = place_array.filter(v => b.size != b.add(JSON.stringify(v)).size, b = new Set());

console.log(result);


Альтернативное решение:

Вы можете использовать filter с локальным Array объектом.Определив, присутствуют ли уже строковые объекты в массиве, и нажав, если их нет, вы можете вернуть уникальный массив, спросив, не включен ли в массив строковый объект.

Код:

place_array.filter(v => !b.includes(s(v)) && !!b.push(s(v)), s = JSON.stringify, b = []);

Зачем использовать этот код?

Эффективный, хотя объект Set может быть, он в конечном итоге медленнее из-за внутренних процессов, чем использование объекта Array.Вы можете легко доказать это, запустив тест, такой как jsperf: https://jsperf.com/set-vs-ray-includes-battle/1

Результаты теста:

Test Results Proving Array is Faster than Set

Рабочий пример:

let place_array = [{
    "places": "NEW YORK",
    "locations": "USA"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },

];

let result = place_array.filter(v => !b.includes(s(v)) && !!b.push(s(v)), s = JSON.stringify, b = []);

console.log(result);
0 голосов
/ 04 апреля 2019

если вы используете подчеркивание, вы можете сделать что-то вроде этого:

var list = [
  {
    "places": "NEW YORK",
    "locations": "USA"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },
  {
    "places": "MONTREAL",
    "locations": "QUEBEC",
    "country": "Canada"
  },

];

var uniqList = _.uniq(list, function (item) {
	return item.places+'_'+item.locations+'_'+item.country;
});

console.log(uniqList);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
0 голосов
/ 04 апреля 2019

Вы можете сделать это так

let data = data.filter(function (a) {
    let key = a.places + '|' + a.country;
    if (!this[key]) {
        this[key] = true;
        return true;
    }
}, Object.create(null));

console.log(data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...