Как найти объекты с одинаковыми значениями свойств в массиве объектов в машинописи? - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть массив объектов

var myArray = [
  {id: 1, name: 'Foo Bar', email: 'foo@bar.com'},
  {id: 2, name: 'Bar Foo', email: 'bar@foo.com'},
  {id: 3, name: 'Joe Ocean', email: 'joe@ocean.com'},
  {id: 3, name: 'Jenny Block', email: 'foo@bar.com'},
];

Я ожидаю следующий вывод:

commonIdsObjects = [
  {id: 3, name: 'Joe Ocean', email: 'joe@ocean.com'},
  {id: 3, name: 'Jenny Block', email: 'foo@bar.com'},

]

Ответы [ 2 ]

1 голос
/ 03 марта 2020
  var myArray = [
{ id: 1, name: "Foo Bar", email: "foo@bar.com" },
{ id: 2, name: "Bar Foo", email: "bar@foo.com" },
{ id: 3, name: "Joe Ocean", email: "joe@ocean.com" },
{ id: 3, name: "Jenny Block", email: "foo@bar.com" }];

const commonIdsObjects = myArray.filter(x => x.id === 3);

console.log(commonIdsObjects);
0 голосов
/ 27 февраля 2020

Я предполагаю, что вы хотите, чтобы вывод представлял собой один массив, содержащий все дублирующиеся записи, даже если некоторые из этих записей имеют разные идентификаторы. Например, если вы добавили {id: 2, name: 'Fishy Joe', email: 'com@foo.bar'} к myArray, результирующее commonIdsObjects будет массивом из четырех элементов: два для id: 2 и два для id: 3. Если это не то, что вам нужно, вам следует указать точное ожидаемое поведение.

В любом случае, если у вас есть тип, соответствующий элементам myArray, например:

type Elem = typeof myArray[number];

И если ваша целевая среда выполнения имеет доступ к Object.values() и Array.prototype.flat() методам, то вы можете написать

const commonIdsObjects = Object.values(
    myArray.reduce<{ [k: number]: Elem[] }>(
        (a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}
    )
).filter(c => c.length > 1).flat(1);

Что мы С помощью myArray.reduce() создается объект, ключи которого соответствуют значениям id ваших элементов, а значения - это массивы элементов с этими id. Мы преобразуем этот объект в массив массивов элементов, сохраняем только те, длина которых больше одного (т. Е. Любой идентификатор с более чем одним элементом, соответствующим ему), и объединяем в один массив.

Это даст желаемый результат:

console.log(JSON.stringify(commonIdsObjects));
// [{"id":3,"name":"Joe Ocean","email":"joe@ocean.com"},
//  {"id":3,"name":"Jenny Block","email":"foo@bar.com"}]

Если у вас нет доступа к Object.values() и [].flat(), вы можете использовать Object.keys() и [].reduce() вместо:

type ElemsById = { [k: string]: Elem[] }
const commonIdsObjects2 = ((o: ElemsById) => Object.keys(o).map(k => o[k]))(
    myArray.reduce<ElemsById>(
        (a, v) => ((a[v.id] || (a[v.id] = [])).push(v), a), {}))
    .filter(c => c.length > 1).reduce<Elem[]>((a, v) => (a.push(...v), a), []);
console.log(JSON.stringify(commonIdsObjects2)); // same

, что по сути тот же алгоритм. Или вы можете сделать этот алгоритм чисто императивным способом программирования с различными for циклами:

const elemsById: ElemsById = {};
for (let v of myArray) {
    if (!elemsById[v.id]) {
        elemsById[v.id] = []
    }
    elemsById[v.id].push(v);
}
const commonIdsObjects3: Elem[] = []
for (let k in elemsById) {
    if (elemsById[k].length <= 1) {
        continue;
    }
    for (let v of elemsById[k]) {
        commonIdsObjects3.push(v);
    }
}
console.log(JSON.stringify(commonIdsObjects3)); // same

Хорошо, надеюсь, это поможет; удачи!

Детская площадка ссылка на код

...