JavaScript/TypeScript: 统计数组中重复的对象,为每个项添加一个“amount”属性

huangapple go评论65阅读模式
英文:

JavaScript/TypeScript: count duplicate Objects in an Array of Objects to have an amount property on Item

问题

你可以尝试以下代码来实现你的目标:

const items = [
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "Used to go fishing.",
    "category": "fishing",
  },
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "Used to go fishing.",
    "category": "fishing",
  },
  {
    "id": "pickaxe",
    "emoji": "⛏️",
    "description": "Used to go mining.",
    "category": "mining",
  },
];

// 创建一个空的对象来存储每个项目的数量
const itemCounts = {};

// 遍历数组并计算每个项目的数量
items.forEach(item => {
  const itemId = item.id;
  if (itemCounts[itemId]) {
    itemCounts[itemId]++;
  } else {
    itemCounts[itemId] = 1;
  }
});

// 将结果放入一个新的数组
const result = Object.keys(itemCounts).map(itemId => ({
  ...items.find(item => item.id === itemId),
  amount: itemCounts[itemId]
}));

console.log(result);

这段代码会输出与你所期望的格式相匹配的结果。

英文:

So I have an array of items. There are duplicate items in that array and I am trying to count these duplicates. The count of those duplicates should be put into one of the duplicate items and the other item should be discarded.

My input:

(simplified)

[
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "Used to go fishing.",
    "category": "fishing",
  },
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "Used to go fishing.",
    "category": "fishing",
  },
  {
    "id": "pickaxe",
    "emoji": "⛏️",
    "description": "Used to go mining.",
    "category": "mining",
  },
],

What I'm looking for:

[
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "Used to go fishing.",
    "category": "fishing",
    "amount": 2
  },
  {
    "id": "pickaxe",
    "emoji": "⛏️",
    "description": "Used to go mining.",
    "category": "mining",
    "amount": 1
  },
]

What I tried so far:

I have tried a few things but couldn't get there.

I've only gotten so far that I was able to only get the Item Id and the count. That looked a like this:

const itemsArray = items.map((i) => i.id); // items being my input array (see top of this post)
const itemsUnique = [...new Set(itemsArray)];
const itemsCount = itemsUnique.map((item) => [item, itemsArray.filter((i) => i === item).length])

Output:

[
  [ "fishing_rod", 2 ],
  [ "pickaxe", 1 ],
]

But that's not really what I am looking for...
A little help would be appreciated. <3

答案1

得分: 0

只需迭代并将具有相同id的项分组:

(以下代码段中有更简洁的版本。)

function mergeItems(items) {
  const grouped = items.reduce((record, item) => {
    if (Object.hasOwn(record, item.id)) {
      record[item.id].count++;
    } else {
      record[item.id] = { ...item, count: 1 };
    }
    return record;
  }, {});
  return Object.values(grouped);
}

尝试一下:

console.config({ maximize: true });

function mergeItems(items) {
  const grouped = items.reduce((record, item) => {
    record[item.id] ??= { ...item, count: 0 };
    record[item.id].count++;
    return record;
  }, {});
  return Object.values(grouped);
}

const input = [
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "用于钓鱼。",
    "category": "钓鱼",
  },
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "用于钓鱼。",
    "category": "钓鱼",
  },
  {
    "id": "pickaxe",
    "emoji": "⛏️",
    "description": "用于采矿。",
    "category": "采矿",
  },
];

console.log(mergeItems(input));
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

希望这有帮助。

英文:

Simply iterate over and group those with the same id:

(A terser version can be found in the snippet below.)

function mergeItems(items) {
  const grouped = items.reduce((record, item) =&gt; {
    if (Object.hasOwn(record, item.id)) {
      record[item.id].count++;
    } else {
      record[item.id] = { ...item, count: 1 };
    }
    return record;
  }, {});
  return Object.values(grouped);
}

Try it:

<!-- begin snippet: js hide: true console: false babel: false -->

<!-- language: lang-js -->

console.config({ maximize: true });

function mergeItems(items) {
  const grouped = items.reduce((record, item) =&gt; {
    record[item.id] ??= { ...item, count: 0 };
    record[item.id].count++;
    return record;
  }, {});
  return Object.values(grouped);
}

const input = [
  {
    &quot;id&quot;: &quot;fishing_rod&quot;,
    &quot;emoji&quot;: &quot;&#127907;&quot;,
    &quot;description&quot;: &quot;Used to go fishing.&quot;,
    &quot;category&quot;: &quot;fishing&quot;,
  },
  {
    &quot;id&quot;: &quot;fishing_rod&quot;,
    &quot;emoji&quot;: &quot;&#127907;&quot;,
    &quot;description&quot;: &quot;Used to go fishing.&quot;,
    &quot;category&quot;: &quot;fishing&quot;,
  },
  {
    &quot;id&quot;: &quot;pickaxe&quot;,
    &quot;emoji&quot;: &quot;⛏️&quot;,
    &quot;description&quot;: &quot;Used to go mining.&quot;,
    &quot;category&quot;: &quot;mining&quot;,
  },
];

console.log(mergeItems(input));

<!-- language: lang-html -->

&lt;script src=&quot;https://gh-canon.github.io/stack-snippet-console/console.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

答案2

得分: 0

我们可以使用 filter 来移除重复项,同时增加计数。

const input = [
  {"id": "fishing_rod", "emoji": "🎣", "description": "Used to go fishing.", "category": "fishing"},
  {"id": "fishing_rod", "emoji": "🎣", "description": "Used to go fishing.", "category": "fishing"},
  {"id": "pickaxe", "emoji": "⛏️", "description": "Used to go mining.", "category": "mining"}
]

const output = input.filter((val, i, arr) => {
  const first = arr.findIndex(({ id }) => val.id === id);
  if (first === i)
    return val.amount = 1; // 当前值是第一次出现
  else arr[first].amount++; // 当前值不是第一次出现
});

console.log(output);

这是代码的翻译部分,没有其他内容。

英文:

We can use filter to remove the duplicates, at the same time incrementing the count.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const input = [{&quot;id&quot;: &quot;fishing_rod&quot;,&quot;emoji&quot;: &quot;&#127907;&quot;,&quot;description&quot;: &quot;Used to go fishing.&quot;,&quot;category&quot;: &quot;fishing&quot;,},{&quot;id&quot;: &quot;fishing_rod&quot;,&quot;emoji&quot;: &quot;&#127907;&quot;,&quot;description&quot;: &quot;Used to go fishing.&quot;,&quot;category&quot;: &quot;fishing&quot;,},{&quot;id&quot;: &quot;pickaxe&quot;,&quot;emoji&quot;: &quot;⛏️&quot;,&quot;description&quot;: &quot;Used to go mining.&quot;,&quot;category&quot;: &quot;mining&quot;,}]

const output = input.filter((val, i, arr) =&gt; {
  const first = arr.findIndex(({ id }) =&gt; val.id === id)
  if(first === i)
    return val.amount = 1 // the current value is the first occurence
  else arr[first].amount++ // the current value is not the first occurence
})

console.log(output)

<!-- end snippet -->

答案3

得分: 0

const source = [
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "用于钓鱼。",
    "category": "钓鱼",
  },
  {
    "id": "fishing_rod",
    "emoji": "🎣",
    "description": "用于钓鱼。",
    "category": "钓鱼",
  },
  {
    "id": "pickaxe",
    "emoji": "⛏️",
    "description": "用于采矿。",
    "category": "采矿",
  },
];

const result = {};
source.forEach((item) => result[item.id] ? result[item.id].amount ++ : result[item.id] = { ...item, amount: 1});
console.log(Object.values(result));

请注意,我已将表情符号和描述部分翻译成中文。

英文:

Technically a one-liner JavaScript/TypeScript: 统计数组中重复的对象,为每个项添加一个“amount”属性

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const source = [
  {
    &quot;id&quot;: &quot;fishing_rod&quot;,
    &quot;emoji&quot;: &quot;&#127907;&quot;,
    &quot;description&quot;: &quot;Used to go fishing.&quot;,
    &quot;category&quot;: &quot;fishing&quot;,
  },
  {
    &quot;id&quot;: &quot;fishing_rod&quot;,
    &quot;emoji&quot;: &quot;&#127907;&quot;,
    &quot;description&quot;: &quot;Used to go fishing.&quot;,
    &quot;category&quot;: &quot;fishing&quot;,
  },
  {
    &quot;id&quot;: &quot;pickaxe&quot;,
    &quot;emoji&quot;: &quot;⛏️&quot;,
    &quot;description&quot;: &quot;Used to go mining.&quot;,
    &quot;category&quot;: &quot;mining&quot;,
  },
];

const result = {};
source.forEach((item) =&gt; result[item.id] ? result[item.id].amount ++ : result[item.id] = { ...item, amount: 1});
console.log(Object.values(result));

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月6日 08:09:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定