JavaScript:为对象数组中的每个唯一值创建一个序列

JavaScript: create a sequence for each unique value in array of objects

我有一个对象数组,我想根据每个值创建一个序列。以数组为例:

let starting_data = [
  {str: "a"},
  {str: "a"},
  {str: "b"},
  {str: "c"},
  {str: "a"},
  {str: "c"},
  {str: "a"},
  {str: "b"}
]

我知道我可以使用 map 和 reduce 找到每个 str 值的唯一编号

let uniques = starting_data.map(function(value) {return value.str;}).reduce((acc, val) => {
      acc[val] = acc[val] === undefined ? 1 : acc[val] += 1;
      return acc;
}, {})

但我不确定如何利用它最终获得我想要的输出:

let desired_output = [
  {str: "a", count: 1},
  {str: "a", count: 2},
  {str: "b", count: 1},
  {str: "c", count: 1},
  {str: "a", count: 3},
  {str: "c", count: 2},
  {str: "a", count: 4},
  {str: "b", count: 2}
]

每个唯一值的计数都重新开始,但是 a 转到 4,bc 转到 2。我试着弄乱 arr.sort 如果我需要先这样做,但我不确定如何根据对象内的值进行排序...感谢任何帮助!

可以做一些事情,比如保留一个单独的对象来跟踪计数

let starting_data = [
  {str: "a"},
  {str: "a"},
  {str: "b"},
  {str: "c"},
  {str: "a"},
  {str: "c"},
  {str: "a"},
  {str: "b"}
]


let counts = {};
let res = starting_data.map(({str}) => {
    if(!counts[str])counts[str]=0;
  counts[str]+=1
  return {str,count:counts[str]}
})

console.log(res)

你提到过你希望它是纯粹的功能性的,所以就在这里。

let starting_data = [
  { str: "a" },
  { str: "a" },
  { str: "b" },
  { str: "c" },
  { str: "a" },
  { str: "c" },
  { str: "a" },
  { str: "b" },
];

const uniqueCount = starting_data
  .reduce(
    (arr, { str }) => {
      const hash = arr[0];
      hash[str] ||= 0;
      arr.push({ str, count: ++hash[str] });
      return arr;
    },
    [{}]
  )
  .slice(1);

console.log(uniqueCount);

这会打印:

[
  { str: 'a', count: 1 },
  { str: 'a', count: 2 },
  { str: 'b', count: 1 },
  { str: 'c', count: 1 },
  { str: 'a', count: 3 },
  { str: 'c', count: 2 },
  { str: 'a', count: 4 },
  { str: 'b', count: 2 }
]

工作原理

此解决方案将散列作为 reduce 构建的数组的第一个元素。

  1. 数组开始于 [{}]
  2. 如果哈希键不存在,则用 0 填充哈希键。
  3. 使用 strcount 将新元素推送到数组。
  4. hash[str]加1,然后作为值。

数组现在看起来像:

[{ a: 1 }, { str: "a", count: 1 }]
  1. 我们继续这样做,直到我们遍历每个项目。
[ { a: 2 }, { str: 'a', count: 1 }, { str: 'a', count: 2 } ]
[ { a: 2, b: 1 }, { str: 'a', count: 1 }, { str: 'a', count: 2 }, { str: 'b', count: 1 } ]
// Continues until it finishes
  1. 最后,我们通过从第一个元素开始对数组进行切片来删除这个初始散列。

希望对您有所帮助。