TypeScript 中的 array.groupBy

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42136098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 04:15:01  来源:igfitidea点击:

array.groupBy in TypeScript

arraystypescriptgroupinghigher-order-functions

提问by Eldamir

The basic array class has .map, .forEach, .filter, and .reduce, but .groupByi noticably absent, preventing me from doing something like

基本数组类有.map, .forEach, .filter, and .reduce,但.groupBy我明显缺席,阻止我做类似的事情

const MyComponent = (props:any) => {
    return (
        <div>
            {
                props.tags
                .groupBy((t)=>t.category_name)
                .map((group)=>{
                    [...]
                })
            }

        </div>
    )
}

I ended up implementing something myself:

我最终自己实现了一些东西:

class Group<T> {
    key:string;
    members:T[] = [];
    constructor(key:string) {
        this.key = key;
    }
}


function groupBy<T>(list:T[], func:(x:T)=>string): Group<T>[] {
    let res:Group<T>[] = [];
    let group:Group<T> = null;
    list.forEach((o)=>{
        let groupName = func(o);
        if (group === null) {
            group = new Group<T>(groupName);
        }
        if (groupName != group.key) {
            res.push(group);
            group = new Group<T>(groupName);
        }
        group.members.push(o)
    });
    if (group != null) {
        res.push(group);
    }
    return res
}

So now I can do

所以现在我可以做

const MyComponent = (props:any) => {
    return (
        <div>
            {
                groupBy(props.tags, (t)=>t.category_name)
                .map((group)=>{
                    return (
                        <ul key={group.key}>
                            <li>{group.key}</li>
                            <ul>
                                {
                                    group.members.map((tag)=>{
                                        return <li key={tag.id}>{tag.name}</li>
                                    })
                                }
                            </ul>
                        </ul>
                    )
                })
            }

        </div>
    )
}

Works pretty well, but it is too bad that I need to wrap the list rather than just being able to chain method calls.

效果很好,但太糟糕了,我需要包装列表而不仅仅是能够链接方法调用。

Is there a better solution?

有更好的解决方案吗?

采纳答案by Andrew Monks

you could add the function to the array prototype in your app (note some don't recomend this: Why is extending native objects a bad practice?):

您可以将该函数添加到您的应用程序中的数组原型中(请注意,有些人不建议这样做:为什么扩展本机对象是一种不好的做法?):

Array.prototype.groupBy = function(/* params here */) { 
   let array = this; 
   let result;
   /* do more stuff here*/
   return result;
}; 

Then create an interface in typescript like this:

然后在打字稿中创建一个界面,如下所示:

.d.ts version:

.d.ts 版本:

    interface Array<T>
    {
        groupBy<T>(func:(x:T) => string): Group<T>[]
    }

OR in a normal ts file:

或者在普通的 ts 文件中:

declare global {
   interface Array<T>
   {
      groupBy<T>(func:(x:T) => string): Group<T>[]
   }
}

Then you can use:

然后你可以使用:

 props.tags.groupBy((t)=>t.category_name)
     .map((group)=>{
                    [...]
                })

回答by Khaino

A good option might be lodash.

一个不错的选择可能是lodash

npm install --save lodash
npm install --save-dev @types/lodash

Just import it import * as _ from 'lodash'and use.

只需导入import * as _ from 'lodash'并使用。

Example

例子

_.groupBy(..)
_.map(..)
_.filter(..)