programing

typeScript의 array.groupBy

megabox 2023. 6. 18. 12:28
반응형

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

꽤 잘 작동하지만, 메소드 호출을 체인으로 연결할 수 있는 것보다 목록을 포장해야 하는 것이 너무 아쉽습니다.

더 좋은 해결책이 있습니까?

다음 코드를 사용하여 유형 스크립트를 사용하여 항목을 그룹화할 수 있습니다.

const groupBy = <T, K extends keyof any>(list: T[], getKey: (item: T) => K) =>
  list.reduce((previous, currentItem) => {
    const group = getKey(currentItem);
    if (!previous[group]) previous[group] = [];
    previous[group].push(currentItem);
    return previous;
  }, {} as Record<K, T[]>);


// A little bit simplified version
const groupBy = <T, K extends keyof any>(arr: T[], key: (i: T) => K) =>
  arr.reduce((groups, item) => {
    (groups[key(item)] ||= []).push(item);
    return groups;
  }, {} as Record<K, T[]>);

따라서 다음과 같은 구조와 배열을 사용하는 경우:

type Person = {
  name: string;
  age: number;
};

const people: Person[] = [
  {
    name: "Kevin R",
    age: 25,
  },
  {
    name: "Susan S",
    age: 18,
  },
  {
    name: "Julia J",
    age: 18,
  },
  {
    name: "Sarah C",
    age: 25,
  },
];

다음과 같이 호출할 수 있습니다.

const results = groupBy(people, i => i.name);

이 경우 문자열 키와 사용자[] 값을 가진 개체를 제공합니다.

여기에는 몇 가지 핵심 개념이 있습니다.

1 - 함수를 사용하여 키를 얻을 수 있습니다. 이렇게 하면 TS 추론 기능을 사용하여 함수를 사용할 때마다 제네릭을 입력할 필요가 없습니다.

2- 를하여를 합니다.K extends keyof any constraint, 인 키가 가 될 수 입니다.string | number | symbol이러한 방식으로 예를 들어 getKey 함수를 사용하여 Date 개체를 문자열로 변환할 수 있습니다.

3- 마지막으로 키 유형의 키와 배열 유형의 값이 포함된 개체를 얻을 수 있습니다.

애플리케이션의 어레이 프로토타입에 이 기능을 추가할 수 있습니다(일부는 권장하지 않습니다).네이티브 개체를 확장하는 것이 좋지 않은 이유는 무엇입니까?:

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

그런 다음 다음과 같은 유형 스크립트로 인터페이스를 만듭니다.

.d.ts 버전:

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

또는 일반 ts 파일의 OR:

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

그런 다음 다음을 사용할 수 있습니다.

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

은 은좋옵다같다습니과음은션▁be다▁might▁a같니습이 될 수 있습니다.lodash.

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

가져오기만 하면 됩니다.import * as _ from 'lodash'사용할 수 있습니다.

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

에 에.groupby를 사용합니다.product의 신의입니다.array

let group = product.reduce((r, a) => {
console.log("a", a);
console.log('r', r);
r[a.organization] = [...r[a.organization] || [], a];
return r;
}, {});

console.log("group", group);

2021년 12월 TC39를 .Array.prototype.groupBy그리고.Array.prototype.groupByToMap함수가 사양 프로세스의 3단계에 도달했습니다.

위에 링크된 README에 따라 두 기능의 모양은 다음과 같습니다.

const array = [1, 2, 3, 4, 5];

// groupBy groups items by arbitrary key.
// In this case, we're grouping by even/odd keys
array.groupBy((num, index, array) => {
  return num % 2 === 0 ? 'even': 'odd';
});

// =>  { odd: [1, 3, 5], even: [2, 4] }

// groupByToMap returns items in a Map, and is useful for grouping using
// an object key.
const odd  = { odd: true };
const even = { even: true };
array.groupByToMap((num, index, array) => {
  return num % 2 === 0 ? even: odd;
});

// =>  Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

위에서 설명한 형식의 JavaScript의 미래 버전으로 끝날 것이라는 100% 보장은 없지만(특히 호환성을 위해 제안을 조정하거나 삭제할 수 있는 가능성은 항상 있음), 그럼에도 불구하고 이것을 갖는 것은 강력한 약속입니다.groupBy기능은 곧 표준 lib에서 제공됩니다.

파급 효과에 의해, 이것은 또한 TypeScript에서도 이러한 기능을 사용할 수 있게 될 것이라는 것을 의미합니다.

언급URL : https://stackoverflow.com/questions/42136098/array-groupby-in-typescript

반응형