在TypeScript中如何统计字符串在字符串数组中的出现次数?

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

How to count string occurrences in an array of strings in TypeScript?

问题

I need to iterate over an array of strings, count the occurrences of each string, and return an object with the value and the number of occurrences.

I'm trying to use the array reduce function to achieve such a thing, but, despite the attempts, I haven't been able to achieve that yet.

So I have the following:

["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"]

I need the output:

[{ name: "tony", matches: 6 }, { name: "kassandra", matches: 2 }]

What should I use to obtain the above output?

I have tried the following:

const names = nameList.map((user) => user.name);

const reduce = names.reduce((p, c) => {
  if (p == c) {
    return { name: p, matches: `idk what put here yet` };
  }
  return c;
});
英文:

I need to iterate over an array of strings, count the occurrences of each string, and return a object with the value and the number of occurrences.

I'm trying to use the array reduce function to achieve such thing, but, despite the attempts, I haven't been able to achieve that yet.

So I have the following:

["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"]

I need the output:

[{ name: "tony", matches: 6 }, { name: "kassandra", matches: 2 }]

What should I use to obtain the above output?

I have tried the following:

const names = nameList.map((user) => user.name);

const reduce = names.reduce((p, c) => {
  if (p == c) {
    return { name: p, matches: `idk what put here yet` };
  }
  return c;
});

答案1

得分: 5

首先,计算数组中每个名称的出现次数。
其次,将其转换为具有所需格式的对象,包括name和它们的matches

const names = ["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"];
const counts = {};
//1.
names.forEach(name => {
  if (counts[name]) {
    counts[name] += 1;
  } else {
    counts[name] = 1;
  }
});
//2.
const result = Object.keys(counts).map(name => {
  return {
    name: name,
    matches: counts[name]
  };
});
console.log(result);

如果要使用.reduce()方法来计算名称的出现次数:

const counts = names.reduce((acc, name) => {
    acc[name] = (acc[name] || 0) + 1;
    return acc;
  }, {});

另一种将出现次数转换回对象的方法是使用Object.entries()

Object.entries(counts).map(([name, matches]) => ({ name, matches }));

两种方法结合使用:

const names = ["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"];
const counts = names.reduce((acc, name) => {
    acc[name] = (acc[name] || 0) + 1;
    return acc;
  }, {});
const result = Object.entries(counts).map(([name, matches]) => ({ name, matches }));
console.log(result);

希望这有帮助。

英文:

Firstly, count the occurrences of each name in the array.
Secondly, convert it into an object with the desired format of name and their matches.

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

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

const names = [&quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;];
const counts = {};
//1.
names.forEach(name =&gt; {
  if (counts[name]) {
    counts[name] += 1;
  } else {
    counts[name] = 1;
  }
});
//2.
const result = Object.keys(counts).map(name =&gt; {
  return {
    name: name,
    matches: counts[name]
  };
});
console.log(result);

<!-- end snippet -->

If you want to use .reduce() approach to counting occurrences of names:

const counts = names.reduce((acc, name) =&gt; {
    acc[name] = (acc[name] || 0) + 1;
    return acc;
  }, {});

Another approach to convert occurrences back into an object using Object.entries()

Object.entries(counts).map(([name, matches]) =&gt; ({ name, matches }));

Two approaches combined:

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

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

const names = [&quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;];
const counts = names.reduce((acc, name) =&gt; {
    acc[name] = (acc[name] || 0) + 1;
    return acc;
  }, {});
const result = Object.entries(counts).map(([name, matches]) =&gt; ({ name, matches }));
console.log(result);

<!-- end snippet -->

答案2

得分: 1

A pure Array::reduce() TypeScript solution.

我们提供了一个聚合对象(在回调中的 r), 在其中存储了2个值:期望输出的结果数组 arr 和一个 map,我们可以轻松地找到现有的数组项以增加找到的匹配项:

A live typescript gist is here.

const names = ["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"];

interface MatchItem {
  name: string,
  matches: number
};

const result = names.reduce((r, name) => {
  const { arr, map } = r;
  const item = map.get(name);
  item ? item.matches++ : map.set(name, arr[arr.length] = { name, matches: 1 });
  return r;
}, { arr: [], map: new Map<string, MatchItem>() }).arr;

console.log(result);

JS version:

const names = ["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"];

const result = names.reduce((r, name) => {
  const { arr, map } = r;
  const item = map.get(name);
  item ? item.matches++ : map.set(name, arr[arr.length] = { name, matches: 1 });
  return r;
}, { arr: [], map: new Map }).arr;

console.log(result);

And a benchmark:

在TypeScript中如何统计字符串在字符串数组中的出现次数?

英文:

A pure Array::reduce() Typescript solution.

We provide an aggregate object (r in the callback) where we store 2 values: the result array arr with the desired output and a map map where we can easily find an existing array items to increment found matches:

A live typescript gist is here.

const names = [&quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;];

interface MatchItem {
  name: string, 
  matches: number
};

const result = names.reduce((r, name) =&gt; {
  const {arr, map} = r;
  const item = map.get(name);
  item ? item.matches++ : map.set(name, arr[arr.length] = { name, matches: 1 });
  return r;
}, { arr: [], map: new Map } as {arr: MatchItem[], map: Map&lt;string, MatchItem&gt;}).arr;

console.log(result);

JS version:

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

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

const names = [&quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;];

const result = names.reduce((r, name) =&gt; {
  const {arr, map} = r;
  const item = map.get(name);
  item ? item.matches++ : map.set(name, arr[arr.length] = { name, matches: 1 });
  return r;
}, { arr: [], map: new Map }).arr;

console.log(result);

<!-- end snippet -->

And a benchmark:

在TypeScript中如何统计字符串在字符串数组中的出现次数?

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

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

&lt;script benchmark data-count=&quot;1&quot;&gt;

// randomly fill with names
const src = &#39;tony kassandra alex peter mike arnold tina maria stephen nicolas samuel sonya natali elena julia&#39;.split(&#39; &#39;);

let i = 16000000;
const names = [];
while (i--) {
    names.push(src[Math.floor(Math.random() * src.length)]);
}

// @benchmark XMehdi01&#39;s solution
const counts = names.reduce((acc, name) =&gt; {
    acc[name] = (acc[name] || 0) + 1;
    return acc;
}, {});
Object.entries(counts).map(([name, matches]) =&gt; ({ name, matches }));

//@benchmark Alexander&#39;s solution
names.reduce((r, name) =&gt; {
    const {arr, map} = r;
    const item = map.get(name);
    item ? item.matches++ : map.set(name, arr[arr.length] = { name, matches: 1 });
    return r;
}, { arr: [], map: new Map }).arr;

&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

答案3

得分: 1

为了实现所需的输出,您可以使用reduce函数以及一个对象来存储每个名称的计数。以下是如何实现的示例:

const nameList = ["tony", "tony", "tony", "tony", "kassandra", "tony", "tony", "kassandra"];

const countMatches = nameList.reduce((acc, curr) => {
  if (acc[curr]) {
    acc[curr]++;
  } else {
    acc[curr] = 1;
  }
  return acc;
}, {});

const result = Object.entries(countMatches).map(([name, matches]) => ({ name, matches }));

console.log(result);

输出:

[
  { name: 'tony', matches: 6 },
  { name: 'kassandra', matches: 2 }
]

在上面的代码中,reduce函数用于迭代nameList数组。累加器(acc)是一个对象,用于跟踪每个名称的计数。如果当前名称(curr)已经作为属性存在于累加器中,计数会增加1。否则,将创建一个新属性,以名称作为键,并初始化计数为1。

reduce操作之后,我们使用Object.entries将对象转换回键值对数组。然后,我们使用map将每个键值对转换为具有namematches属性的对象。最后,将结果存储在result变量中。

注意:在您尝试的代码中,您使用了等号运算符(==)来比较pc,这只会比较值,而不是出现的次数。另外,您没有处理名称与前一个名称不相等的情况。

英文:

To achieve the desired output, you can use the reduce function along with an object to store the counts of each name. Here's an example of how you can implement it:

const nameList = [&quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;, &quot;tony&quot;, &quot;tony&quot;, &quot;kassandra&quot;];

const countMatches = nameList.reduce((acc, curr) =&gt; {
  if (acc[curr]) {
    acc[curr]++;
  } else {
    acc[curr] = 1;
  }
  return acc;
}, {});

const result = Object.entries(countMatches).map(([name, matches]) =&gt; ({ name, matches }));

console.log(result);

Output:


[
  { name: &#39;tony&#39;, matches: 6 },
  { name: &#39;kassandra&#39;, matches: 2 }
]

In the code above, the reduce function is used to iterate over the nameList array. The accumulator (acc) is an object that keeps track of the count for each name. If the current name (curr) already exists as a property in the accumulator, the count is incremented by 1. Otherwise, a new property is created with the name as the key and an initial count of 1.

After the reduce operation, we use Object.entries to convert the object back into an array of key-value pairs. Then, we use map to transform each key-value pair into an object with name and matches properties. Finally, the result is stored in the result variable.

Note: In your attempted code, you were comparing p and c using the equality operator (==) which would only compare the values, not the count of occurrences. Additionally, you didn't handle the case where the name is not equal to the previous one.

huangapple
  • 本文由 发表于 2023年6月29日 23:03:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582294.html
匿名

发表评论

匿名网友

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

确定