Javascript / ES6找到唯一的元素并在数组中计数。

时间:2022-01-29 21:20:26

Take an imaginary array of sold items where we oddly enough only are interested in the item title and value:

假设我们只对物品的标题和价值感兴趣,那么我们假设有一个出售物品的数组:

let items = [
    { title: "Trumping the Horns", value: 5.95 },
    { title: "Rocking about", value: 20.00 },
    { title: "Trumping the Horns", value: 5.95 }
]

I know I can get an array with the unique values rather easily:

我知道我可以很容易地得到一个具有唯一值的数组:

const uniqueSales = [...new Set(items.map(item => item.title))];

But lets for instance say I want to know how many of each item I have sold, or the accumulated value of them? So:

但是,比方说,我想知道我卖出了多少件商品,或者它们的累计价值是多少?所以:

[
    { title: "Trumping the Horns", amount: 2 },
    { title: "Rocking about", amount: 1 }
]

Is it possible to map those as well, without having to do some crazy sorting and iterating over that array? Preferebly in a one-liner. The main reason for not doing it server side is that I have a fair amount of different manipulations of the same data, and it seems most correct to just send it once and let the client handle the manipulations and presentations of the data.

是否也可以映射它们,而不需要做一些疯狂的排序和遍历那个数组?Preferebly一行程序。不进行it服务器端操作的主要原因是,我对相同的数据进行了大量不同的操作,似乎最正确的做法是只发送一次,让客户端处理数据的操作和表示。

5 个解决方案

#1


2  

You could use Map and store the reference to the new inserted objects of the result array.

您可以使用映射并存储对结果数组新插入对象的引用。

var items = [{ title: "Trumping the Horns", value: 5.95 }, { title: "Rocking about", value: 20.00 }, { title: "Trumping the Horns", value: 5.95 }],
    result = items.reduce(
        (map => (r, a) => (!map.has(a.title) && map.set(a.title, r[r.push({ title: a.title, amount: 0 }) - 1]), map.get(a.title).amount++, r))(new Map),
        []
    );

console.log(result)

#2


1  

let items = [{
    title: "Trumping the Horns",
    value: 5.95
  },
  {
    title: "Rocking about",
    value: 20.00
  },
  {
    title: "Trumping the Horns",
    value: 5.95
  }
];

console.log(items.reduce(function(countMap, item) {
  countMap[item.title] = ++countMap[item.title] || 1;
  return countMap;
}, {}));

#3


1  

Given the format you want in the end, I don't think it gets much shorter than using a Map to build up objects with the title and amount, then grabbing the Map's values:

考虑到你最终想要的格式,我认为它不会比使用一个带有标题和数量的地图来构建对象,然后获取地图的值要短得多:

const items = [
    { title: "Trumping the Horns", value: 5.95 },
    { title: "Rocking about", value: 20.00 },
    { title: "Trumping the Horns", value: 5.95 }
];
const map = new Map();
items.forEach(item => {
  const entry = map.get(item.title);
  if (!entry) {
    map.set(item.title, {title: item.title, amount: 1});
  } else {
    ++entry.amount;
  }
});
const uniqueSales = [...map.values()];
console.log(uniqueSales);

...preferably a one-liner...

…最好一行程序……

The above can be shoehorned into fewer lines, but it doesn't improve speed, readability, or maintainability. Quite the opposite.

上面的代码可以被压缩到更少的代码行中,但是它不能提高速度、可读性或可维护性。恰恰相反。

#4


0  

I would use a map rather than an array for storing your items, where the key of the map should be the title of the item, and the value should be the quantity of the sold items. Each time, before you add a new item to the map, you should check, whether the key already exist, and if it does, then increase the quantity, otherwise add a new key-value pair to the map.

我将使用映射而不是数组来存储项目,其中映射的键应该是项目的标题,值应该是已售项目的数量。每次在向映射添加新项之前,都应该检查键是否已经存在,如果已经存在,则增加数量,否则向映射添加新的键值对。

#5


0  

 let array = [{title:"123"}, {title: "234"}, {title: "123"}]
 let sum = array.reduce((results, item, index) => {
                      let totalItem = results.find((element) =>
                            element.title == item.title)
                      if(totalItem){
                        totalItem.count += 1
                      }else {
                         results.push(Object.assign(item, {
                              count: 1
                            }))
                      }
                       return results
                     }, [])

use array reduce to generate new array

使用数组reduce生成新数组。

#1


2  

You could use Map and store the reference to the new inserted objects of the result array.

您可以使用映射并存储对结果数组新插入对象的引用。

var items = [{ title: "Trumping the Horns", value: 5.95 }, { title: "Rocking about", value: 20.00 }, { title: "Trumping the Horns", value: 5.95 }],
    result = items.reduce(
        (map => (r, a) => (!map.has(a.title) && map.set(a.title, r[r.push({ title: a.title, amount: 0 }) - 1]), map.get(a.title).amount++, r))(new Map),
        []
    );

console.log(result)

#2


1  

let items = [{
    title: "Trumping the Horns",
    value: 5.95
  },
  {
    title: "Rocking about",
    value: 20.00
  },
  {
    title: "Trumping the Horns",
    value: 5.95
  }
];

console.log(items.reduce(function(countMap, item) {
  countMap[item.title] = ++countMap[item.title] || 1;
  return countMap;
}, {}));

#3


1  

Given the format you want in the end, I don't think it gets much shorter than using a Map to build up objects with the title and amount, then grabbing the Map's values:

考虑到你最终想要的格式,我认为它不会比使用一个带有标题和数量的地图来构建对象,然后获取地图的值要短得多:

const items = [
    { title: "Trumping the Horns", value: 5.95 },
    { title: "Rocking about", value: 20.00 },
    { title: "Trumping the Horns", value: 5.95 }
];
const map = new Map();
items.forEach(item => {
  const entry = map.get(item.title);
  if (!entry) {
    map.set(item.title, {title: item.title, amount: 1});
  } else {
    ++entry.amount;
  }
});
const uniqueSales = [...map.values()];
console.log(uniqueSales);

...preferably a one-liner...

…最好一行程序……

The above can be shoehorned into fewer lines, but it doesn't improve speed, readability, or maintainability. Quite the opposite.

上面的代码可以被压缩到更少的代码行中,但是它不能提高速度、可读性或可维护性。恰恰相反。

#4


0  

I would use a map rather than an array for storing your items, where the key of the map should be the title of the item, and the value should be the quantity of the sold items. Each time, before you add a new item to the map, you should check, whether the key already exist, and if it does, then increase the quantity, otherwise add a new key-value pair to the map.

我将使用映射而不是数组来存储项目,其中映射的键应该是项目的标题,值应该是已售项目的数量。每次在向映射添加新项之前,都应该检查键是否已经存在,如果已经存在,则增加数量,否则向映射添加新的键值对。

#5


0  

 let array = [{title:"123"}, {title: "234"}, {title: "123"}]
 let sum = array.reduce((results, item, index) => {
                      let totalItem = results.find((element) =>
                            element.title == item.title)
                      if(totalItem){
                        totalItem.count += 1
                      }else {
                         results.push(Object.assign(item, {
                              count: 1
                            }))
                      }
                       return results
                     }, [])

use array reduce to generate new array

使用数组reduce生成新数组。