web-dev-qa-db-ja.com

TypeScriptのarray.groupBy

基本的な配列クラスには.map.forEach.filter.reduce、 だが .groupBy不在のため、次のようなことができません

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

        </div>
    )
}

私は自分で何かを実装することになりました:

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
}

だから今できる

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>
    )
}

かなりうまくいきますが、メソッド呼び出しをチェーンするだけではなく、リストをラップする必要があるのは残念です。

より良い解決策はありますか?

6
Eldamir

あなたはあなたのアプリの配列プロトタイプに関数を追加することができます(これをお勧めしない人もいることに注意してください: なぜネイティブオブジェクトを拡張することは悪い習慣ですか? ):

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

次に、次のようにTypeScriptでインターフェイスを作成します。

.d.tsバージョン:

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

または通常のtsファイルで:

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

それからあなたは使うことができます:

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

良いオプションはlodashかもしれません。

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

インポートするだけですimport * as _ from 'lodash'と使用します。

_.groupBy(..)
_.map(..)
_.filter(..)
0
Khaino