查找数组中的重复对象,并返回新的对象数组,其中重复项的数量作为新属性

Ess*_*zed 5 javascript arrays object filter

所以我有一个对象数组,例如如下所示:

let arrayOfObjects = [
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  }
];
Run Code Online (Sandbox Code Playgroud)

我需要遍历它,找到重复项,并为每个重复项仅返回一个对象,但将重复项的数量作为新参数。

像这样:

let newArrayOfObjects = [
  {
    Name: "Apple",
    Type: "Fruit",
    times: 3,
  },
  {
    Name: "Carrot",
    Type: "Vegetable",
    times: 4,
  }
];
Run Code Online (Sandbox Code Playgroud)

我可以根据一个参数计算重复的对象,但我不知道如何根据整个对象进行计算。解决这个问题的最佳方法是什么?

Gor*_*nov 10

您可以结合使用.map原始数组并使用 搜索新形成的数组的项目来完成此操作.find

    let arrayOfObjects = [
    {
      Name: "Apple",
      Type: "Fruit"
    },
    {
      Name: "Carrot",
      Type: "Vegetable"
    },
    {
      Name: "Carrot",
      Type: "Vegetable"
    },
    {
      Name: "Carrot",
      Type: "Vegetable"
    },
    {
      Name: "Apple",
      Type: "Fruit"
    },
    {
      Name: "Apple",
      Type: "Fruit"
    },
    {
      Name: "Carrot",
      Type: "Vegetable"
    }
  ];

const resultArray = [];

arrayOfObjects.map(item => {
    //for each item in arrayOfObjects check if the object exists in the resulting array
    if(resultArray.find(object => {
        if(object.Name === item.Name && object.Type === item.Type) {
            //if the object exists iterate times
            object.times++;
            return true;
            //if it does not return false
        } else {
            return false;
        }
    })){
    } else {
        //if the object does not exists push it to the resulting array and set the times count to 1
        item.times = 1;
        resultArray.push(item);
    }
})

console.log(resultArray)
Run Code Online (Sandbox Code Playgroud)

更新:

最好使用.reduce而不是,.map因为后者主要用于对数组的每个元素应用某个函数并获取函数执行结果的数组。

.reduce()另一方面,数组方法也在每个项目上执行一个函数(回调),但它将结果从一个元素数组传递到另一个元素数组。因此,我们可以使用一个空数组作为开始,并用一个对象或迭代.times属性填充它,以防当前元素存在于传递给每个回调的累积数组中。

这是一个例子:

let arrayOfObjects = [
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  },
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Apple",
    Type: "Fruit"
  },
  {
    Name: "Carrot",
    Type: "Vegetable"
  }
];


const newArrayOfObjects = 
  arrayOfObjects.reduce((accumulator, object) => {
    if(objectFound = accumulator.find(arrItem => arrItem.Name === object.Name && arrItem.Type === object.Type)) {
        objectFound.times++;
    } else {
        object.times = 1;
        accumulator.push(object);
    }
    return accumulator;
  }, []);

console.log(newArrayOfObjects);
Run Code Online (Sandbox Code Playgroud)


Neg*_*ion 3

我认为创建一个辅助对象最适合您。辅助对象最初是空的,但会慢慢地被您正在阅读的内容填充。我假设数组中的键是一致的。

const keys = ["Name","Type"]
var counterObj = {}
let keyForCounterObj
arrayOfObjects.forEach((obj)=>{
    keyForCounterObj = ''
    keys.forEach((key)=>{
        keyForCounterObj += String(obj[key])
}
if(counterObj[keyForCounterObj]){
    counterObj[keyForCounterObj].times ++
}else{
    counterObj[keyForCounterObj] = {
        ...obj,
        times:1
}}}
Run Code Online (Sandbox Code Playgroud)

让我们来分解一下,因为我知道如果您以前从未见过这个设置,可能会有点困惑。

我们循环遍历数组中的每个对象,并根据该对象存储的所有值构造一个键。例如,arrayOfObjects[0] 将创建“AppleFruit”键。(我使用 String() 方法只是为了将该方法应用于仅具有整数或浮点值的对象,因为这些值在 javaScript 中创建键无效。对于您的具体问题来说这不是必需的)

一旦我们有了这个密钥,我们就检查它是否存在于我们的 counterObject 中。如果它不存在,那么我们定义它。我们将“times”属性设置为1,因为我们刚刚创建了这个对象;除非我们刚刚发现它,否则它不会存在。

如果该对象已经存在,那么我们只需增加“times”属性。最后,我们有一个如下所示的对象:

counterObj = {
    AppleFruit: {
        Name:"Apple",
        Type:"Fruit",
        times:3,
    },
    CarrotVegetable:{
        Name:"Carrot",
        Type:"Vegetable",
        times:4,
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,现在我们有了一个对象的对象。让我们把它变成一个数组!

let newArrayOfObjects = []
const counterObjKeys = Object.keys(counterObj)
counterObjKeys.forEach((key)=>{
    newArrayOfObjects.push(counterObj[key])
}
Run Code Online (Sandbox Code Playgroud)

这将以您指定的格式返回最终值!