英文:
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 = ["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);
<!-- end snippet -->
If you want to use .reduce()
approach to counting occurrences of names:
const counts = names.reduce((acc, name) => {
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]) => ({ name, matches }));
Two approaches combined:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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);
<!-- 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:
英文:
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 = ["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 } as {arr: MatchItem[], map: Map<string, MatchItem>}).arr;
console.log(result);
JS version:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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);
<!-- end snippet -->
And a benchmark:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<script benchmark data-count="1">
// randomly fill with names
const src = 'tony kassandra alex peter mike arnold tina maria stephen nicolas samuel sonya natali elena julia'.split(' ');
let i = 16000000;
const names = [];
while (i--) {
names.push(src[Math.floor(Math.random() * src.length)]);
}
// @benchmark XMehdi01's solution
const counts = names.reduce((acc, name) => {
acc[name] = (acc[name] || 0) + 1;
return acc;
}, {});
Object.entries(counts).map(([name, matches]) => ({ name, matches }));
//@benchmark Alexander's solution
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;
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
<!-- 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
将每个键值对转换为具有name
和matches
属性的对象。最后,将结果存储在result
变量中。
注意:在您尝试的代码中,您使用了等号运算符(==
)来比较p
和c
,这只会比较值,而不是出现的次数。另外,您没有处理名称与前一个名称不相等的情况。
英文:
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 = ["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);
Output:
[
{ name: 'tony', matches: 6 },
{ name: 'kassandra', 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论