提问人:Jameson 提问时间:3/8/2023 更新时间:3/8/2023 访问量:96
在 Typescript 的回调函数中对 JSON 中的数据进行分组
Group data from JSON in callback function in Typescript
问:
我需要编写一个函数 groupBy,它使用给定的函数对 JSON 数据中的人员进行分组。 下面是接口和 JSON 数据:
interface Person {
name: string;
yearOfBirth: number;
placeOfBirth: string;
}
const input: Person[] = [
{
name: "Andy",
yearOfBirth: 1984,
placeOfBirth: "New York",
},
{
name: "John",
yearOfBirth: 1995,
placeOfBirth: "New York",
},
{
name: "Bill",
yearOfBirth: 1995,
placeOfBirth: "Orlando",
},
{
name: "Tim",
yearOfBirth: 1989,
placeOfBirth: "Witchita",
},
];
以下是我到目前为止拥有的代码,它离应有的工作还差得很远,但我是回调函数的新手,所以我一直在尝试了解它是如何工作的。
const groupBy = (input: Person[], func: (p: Person) => string): string[] => {
let collect: string[] = [];
for (let i = 0; i < input.length; i++) {
collect[i] = func(input[i]);
}
return collect;
}
try {
console.log(groupBy(input, (p: Person) => p.placeOfBirth));
}
catch (e: any) {
console.log(e.message);
}
//This is the output from my current code:
[ 'New York', 'New York', 'Orlando', 'Witchita' ]
以下是使用下面的控制台 .log 调用时实际输出的方式:
//Example 1
//call the function which groups the data together from 'placeOfBirth':
console.log(groupBy(input, (p: Person) => p.placeOfBirth));
//Output from console.log:
{
New York: [
{ name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' },
{ name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' }
],
Orlando: [ { name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' } ],
Witchita: [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ]
}
//Example 2
//call the function which groups the data together from 'yearOfBirth':
console.log(groupBy(input, (p: Person) => p.yearOfBirth));
//Output from console.log:
{
'1984': [ { name: 'Andy', yearOfBirth: 1984, placeOfBirth: 'New York' } ],
'1995': [
{ name: 'John', yearOfBirth: 1995, placeOfBirth: 'New York' },
{ name: 'Bill', yearOfBirth: 1995, placeOfBirth: 'Orlando' }
],
'1989': [ { name: 'Tim', yearOfBirth: 1989, placeOfBirth: 'Witchita' } ]
}
答:
0赞
Amin Pourhadi
3/8/2023
#1
使用以下函数。传递对象数组和键名称进行分组,然后按发送的键获取分组数据:
const groupByKey = <T>(objectArray: T[], property: string) => {
return objectArray.reduce(
(acc: { [x: string]: any[]; }, obj: { [x: string]: any; }) => {
const key = obj[property];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(obj);
return acc;
},
{});
}
//Usage:
const groupedData = groupByKey(personsList, 'placeOfBirth');
评论
0赞
Jameson
3/8/2023
嘿,感谢您的回复,但是我在您的代码中遇到一些错误,代码行为'(acc: { [x: string]: any[]; }, obj: { [x: string]: any; })'类型为 '(acc: { [x: string]: any[]; }, obj: { [x: string]: any; }) => { [x: string]: any[]; }' 的参数不能分配给类型为 '(previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T' 的参数。参数“acc”和“previousValue”的类型不兼容。
0赞
Florian Sénat
3/8/2023
#2
您是否专注于性能?
如果没有,您可以尝试以下操作:
function groupBy<I extends unknown>(
input: I[],
predicate: (i: I) => string | number
) {
return input.reduce((curr, i) => {
const key = predicate(i);
return {
...curr,
[key]: [...(curr[key] ?? []), i]
};
}, {});
}
这里有一个沙盒来尝试一下:https://codesandbox.io/s/unruffled-morse-nwjjsy?file=/src/index.ts
评论
0赞
Jameson
3/8/2023
感谢您的回复。我在您的代码中收到“curr[key]”中的错误:(参数)curr:{} 元素隐式具有“any”类型,因为“string |number“不能用于索引类型”{}”。在类型“{}”上找不到参数类型为“string”的索引签名.ts(7053)
0赞
Jameson
3/8/2023
#3
我找到了一个解决方案,最终可以将数据组合在一起。我将为其他任何寻找类似解决方案的人分享下面的代码:
interface Person {
name: string;
yearOfBirth: number;
placeOfBirth: string;
}
const input: Person[] = [
{
name: "Andy",
yearOfBirth: 1984,
placeOfBirth: "New York",
},
{
name: "John",
yearOfBirth: 1995,
placeOfBirth: "New York",
},
{
name: "Bill",
yearOfBirth: 1995,
placeOfBirth: "Orlando",
},
{
name: "Tim",
yearOfBirth: 1989,
placeOfBirth: "Witchita",
},
];
function groupBy(input: Person[], groupFunc: (item: Person) => any): { [key: string]: Person[] } {
const groups: { [key: string]: Person[] } = {};
input.forEach(item => {
const groupKey = groupFunc(item);
if (!groups[groupKey]) {
groups[groupKey] = [];
}
groups[groupKey].push(item);
});
return groups;
}
try {
console.log(groupBy(input, (p: Person) => p.yearOfBirth));
}
catch (e: any) {
console.log(e.message);
}
export { }
评论