如何在打字稿中的对象数组中查找具有相同 属性 值的对象?

How to find objects with the same property values in an Array of Objects in typescript?

我有一个对象数组

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'},

]

我假设您希望输出是包含所有重复条目的单个数组,即使其中一些条目具有不同的 ID。例如,如果您将 {id: 2, name: 'Fishy Joe', email: 'com@foo.bar'} 添加到 myArray,生成的 commonIdsObjects 将是一个包含四个项目的数组:两个用于 id: 2,两个用于 id: 3。如果这不是您想要的,那么您应该注意准确指定预期的行为。

无论如何,假设你有一个对应于 myArray 元素的类型,像这样:

type Elem = typeof myArray[number];

假设您的目标运行时可以访问 Object.values() and 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 的元素数组。我们将此对象转换为元素数组的数组,仅保留长度大于 1 的元素(即,具有多个元素对应的任何 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

好的,希望对您有所帮助;祝你好运!

Playground link to code

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