Programing

ILookup

lottogame 2020. 10. 25. 11:28
반응형

ILookup 대 IGrouping


나는 사이의 차이를 분명히 말하는 데 문제가 있었어요 ILookup<TKey, TVal>하고 IGrouping<TKey, TVal>, 나는 지금 제대로 이해한다면 궁금합니다. LINQ는 IGrouping항목 시퀀스를 생성하는 동시에 ToLookup확장 방법을 제공 하여 문제를 복잡하게했습니다 . 그래서 좀 더 자세히보기 전까지는 똑같은 느낌이었습니다.

var q1 = 
    from n in N
    group n by n.MyKey into g
    select g;
// q1 is IEnumerable<IGrouping<TKey, TVal>>

다음과 같습니다.

var q2 = N.GroupBy(n => n.MyKey, n => n);
// q2 is IEnumerable<IGrouping<TKey, TVal>>

다음과 같이 보입니다.

var q3 = N.ToLookup(n => n.MyKey, n => n);
// q3 is ILookup<TKey, TVal>

나는 다음 비유에서 맞습니까?

  1. An IGrouping<TKey, TVal>KeyValuePair<TKey, TVal>값이 실제로 요소의 시퀀스 (단일 요소가 아닌 ) 인 경우와 유사한 단일 그룹 (예 : 키순 )입니다.
  2. An IEnumerable<IGrouping<TKey, TVal>>은 그것들의 시퀀스입니다 (반복 할 때 얻는 것과 유사합니다.IDictionary<TKey, TVal>
  3. An ILookup<TKey, TVal>IDictionary<TKey, TVal>값이 실제로 요소의 시퀀스 인 것과 비슷합니다 .

예, 모두 정확합니다.

그리고 ILookup<TKey, TValue>또한 확장 IEnumerable<IGrouping<TKey, TValue>>모든 키 / 수집 쌍을 반복뿐만 아니라 (또는 대신에) 단지 특정 키를 찾는 수 있습니다.

기본적으로 내가 생각 ILookup<TKey,TValue>처럼 것으로 IDictionary<TKey, IEnumerable<TValue>>.

마음에 베어 ToLookupA는 반면 "지금 당장"작업 (즉시 실행)입니다 GroupBy지연됩니다. "pull LINQ"가 작동하는 방식 IGrouping으로 a 결과에서 s를 가져 오기 시작 GroupBy하면 (중간에 그룹을 전환 할 수 없기 때문에) 어쨌든 모든 데이터를 읽어야하는 반면 다른 구현에서는 스트리밍 결과를 생성 할 수 있습니다. (Push LINQ에서 수행됩니다. LINQ to Events가 동일 할 것으로 예상합니다.)


ILookup과 IDictionary 사이에는 또 다른 중요한 차이점이 있습니다. 전자는 여기에 데이터를 변경하는 방법이 없다는 점에서 불변성을 적용합니다 (소비자가 명시 적 캐스트를 수행하는 경우 제외). 반대로 IDictionary에는 데이터를 변경할 수있는 "Add"와 같은 메서드가 있습니다. 따라서 기능 프로그래밍 및 / 또는 병렬 프로그래밍의 관점에서 보면 ILookup이 더 좋습니다. (그룹이 아닌 키에 하나의 값만 할당하는 ILookup 버전도 있었으면합니다.)

(Btw., IEnumerable과 IList 사이의 관계는 ILookup과 IDictionary 사이의 관계와 다소 유사하다는 점을 지적 할 가치가있는 것 같습니다. 전자는 불변이고 후자는 그렇지 않습니다.)


GroupBy다음을 제외ToLookUp 하고 거의 동일한 기능 이 있습니다. 참조

GroupBy : GroupBy 연산자는 일부 키 값을 기반으로 요소 그룹을 반환합니다. 각 그룹은 IGrouping 개체로 표시됩니다.

ToLookup : ToLookup은 GroupBy와 동일합니다. 유일한 차이점은 GroupBy 실행이 지연되는 반면 ToLookup 실행은 즉시 수행된다는 것입니다.

샘플 코드를 사용하여 차이점을 정리해 보겠습니다. Person모델을 나타내는 클래스가 있다고 가정합니다 .

class Personnel
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int Level { get; set; }
}

그 후 personnels아래와 같이 목록을 정의 합니다.

 var personnels = new List<Personnel>
    {
        new Personnel { Id = 1, FullName = "P1", Level = 1 },
        new Personnel { Id = 2, FullName = "P2", Level = 2 },
        new Personnel { Id = 3, FullName = "P3", Level = 1 },
        new Personnel { Id = 4, FullName = "P4", Level = 1 },
        new Personnel { Id = 5, FullName = "P5", Level =2 },
        new Personnel { Id = 6, FullName = "P6", Level = 2 },
        new Personnel { Id = 7, FullName = "P7", Level = 2 }
    };

이제 personnels레벨별로 그룹화해야합니다. 여기에 두 가지 접근 방식이 있습니다. 사용 GroupBy또는 ToLookUp. 내가 사용하는 경우 GroupBy, 이전에 언급 한 바와 같이, 그것은 연기 실행이 수단을 사용이 요구 될 때까지 반복 처리가 컬렉션을 통해 다음 항목이나 계산되지 않을 수 있습니다 때.

 var groups = personnels.GroupBy(p => p.Level);
    personnels.RemoveAll(p => p.Level == 1);
    foreach (var product in groups)
    {
        Console.WriteLine(product.Key);
        foreach (var item in product)
            Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
    }

In the above code, I firstly grouped the personnels, but before iterating it, I removed some personnels. As GroupBy uses deferred execution, so the final result will not include the removed items, because grouping will be computing in the foreach point here.

Output:

2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

But if I rewrite the above code as below:(note that code is same as the previous code except GroupBy is replaced by ToLookUp)

 var groups = personnels.ToLookup(p => p.Level);
    personnels.RemoveAll(p => p.Level == 1);
    foreach (var product in groups)
    {
        Console.WriteLine(product.Key);
        foreach (var item in product)
            Console.WriteLine(item.Id + " >>> " + item.FullName + " >>> " + item.Level);
    }

As ToLookUp uses immediate execution, it means that when I call the ToLookUp method, result is generated and group is applied, so if I remove any item from personnels prior to iteration, that wont effect the final result.

Output:

1
1 >>> P1 >>> 1
3 >>> P3 >>> 1
4 >>> P4 >>> 1
2
2 >>> P2 >>> 2
5 >>> P5 >>> 2
6 >>> P6 >>> 2
7 >>> P7 >>> 2

Note: GroupBy and ToLookUp both return different types too.

You might use ToDictionary instead of ToLookUp, but you need to pay attention to this:(reference)

The usage of ToLookup() is very similar to that of ToDictionary(), both allow you to specify key selectors, value selectors, and comparers. The main difference is that ToLookup() allows (and expects) the duplicate keys whereas ToDictionary() does not

참고URL : https://stackoverflow.com/questions/1337539/ilookuptkey-tval-vs-igroupingtkey-tval

반응형