Development Tip

여러 요소 컬렉션을 결합하는 우아한 방법?

yourdevel 2020. 10. 11. 11:29
반응형

여러 요소 컬렉션을 결합하는 우아한 방법?


각각 동일한 유형 (예 : List<int> fooList<int> bar)의 개체를 포함하는 임의의 수의 컬렉션이 있다고 가정 해 보겠습니다 . 이러한 컬렉션이 컬렉션에 포함 된 경우 (예 : 유형의 List<List<int>>) SelectMany모든 컬렉션을 하나의 컬렉션으로 결합하는 데 사용할 수 있습니다 .

그러나 이러한 컬렉션이 아직 동일한 컬렉션에없는 경우 다음과 같은 메서드를 작성해야한다는 느낌이 듭니다.

public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
   return toCombine.SelectMany(x => x);
}

나는 다음과 같이 부를 것입니다.

var combined = Combine(foo, bar);

Combine위와 같은 유틸리티 메서드를 작성하지 않고도 (여러 개의) 컬렉션을 결합하는 깨끗하고 우아한 방법이 있습니까? LINQ에서 할 수있는 방법이 있어야 할만큼 간단 해 보이지만 아닐 수도 있습니다.


LINQ를 찾고 .Concat()계십니까?

var combined = foo.Concat(bar).Concat(foobar).Concat(...);

또는 .Union()중복 요소를 제거합니다.


Concat확장 메서드로서 에게 연결하는 큰 시퀀스가 ​​여러 개있을 때 코드에서 그다지 우아하지 않습니다. 이것은 코드 들여 쓰기 / 서식 문제 일 뿐이며 매우 개인적인 문제입니다.

물론 다음과 같이 보입니다.

var list = list1.Concat(list2).Concat(list3);

다음과 같이 읽을 때 그렇게 읽을 수 없습니다.

var list = list1.Select(x = > x)
   .Concat(list2.Where(x => true)
   .Concat(list3.OrderBy(x => x));

또는 다음과 같은 경우 :

return Normalize(list1, a, b)
    .Concat(Normalize(list2, b, c))
       .Concat(Normalize(list3, c, d));

또는 원하는 형식이 무엇이든. 더 복잡한 연결을 사용하면 상황이 악화됩니다. 내 그 이유 의 종류 위의 스타일인지 부조화는 첫 번째 순서 거짓말 외부 있다는 것입니다 Concat이후의 시퀀스 반면, 방법은 내부 거짓말. Concat확장 스타일이 아닌 정적 메서드를 직접 호출하는 것을 선호합니다 .

var list = Enumerable.Concat(list1.Select(x => x),
                             list2.Where(x => true));

더 많은 수의 시퀀스 연결을 위해 OP에서와 동일한 정적 방법을 수행합니다.

public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sequences)
{
    return sequences.SelectMany(x => x);
}

그래서 다음과 같이 쓸 수 있습니다.

return EnumerableEx.Concat
(
    list1.Select(x = > x),
    list2.Where(x => true),
    list3.OrderBy(x => x)
);

더 좋아 보인다. 내가 작성해야하는 여분의 중복 클래스 이름은 내 시퀀스가 Concat호출로 더 깨끗해 보이기 때문에 문제가되지 않습니다 . C # 6 에서는 문제가 적습니다 . 다음과 같이 작성할 수 있습니다.

return Concat(list1.Select(x = > x),
              list2.Where(x => true),
              list3.OrderBy(x => x));

C #에서 다음과 같은 목록 연결 연산자가 있기를 바랍니다.

list1 @ list2 // F#
list1 ++ list2 // Scala

그렇게하면 훨씬 더 깨끗해집니다.


당신이 경우에 즉, 컬렉션의 컬렉션을 가지고 List<List<T>>, Enumerable.Aggregate하나에 모든 목록을 결합하는 더 우아한 방법입니다 :

var combined = lists.Aggregate((acc, list) => { return acc.Concat(list); });

다음 Enumerable.Concat과 같이 사용하십시오 .

var combined = foo.Concat(bar).Concat(baz)....;

사용 Enumerable.Concact:

var query = foo.Concat(bar);

항상 Concat과 결합 된 Aggregate를 사용할 수 있습니다.

        var listOfLists = new List<List<int>>
        {
            new List<int> {1, 2, 3, 4},
            new List<int> {5, 6, 7, 8},
            new List<int> {9, 10}
        };

        IEnumerable<int> combined = new List<int>();
        combined = listOfLists.Aggregate(combined, (current, list) => current.Concat(list)).ToList();

내가 보는 유일한 방법은 Concat()

 var foo = new List<int> { 1, 2, 3 };
 var bar = new List<int> { 4, 5, 6 };
 var tor = new List<int> { 7, 8, 9 };

 var result = foo.Concat(bar).Concat(tor);

그러나 더 나은 것을 결정해야합니다.

var result = Combine(foo, bar, tor);

또는

var result = foo.Concat(bar).Concat(tor);

더 나은 선택 이되는 이유Concat() 중 하나 는 다른 개발자에게 더 분명 할 것이라는 점입니다. 더 읽기 쉽고 간단합니다.


You can use Union as follows:

var combined=foo.Union(bar).Union(baz)...

This will remove identical elements, though, so if you have those, you might want to use Concat, instead.


Given that you're starting with a bunch of separate collections, I think your solution is rather elegant. You're going to have to do something to stitch them together.

It would be more convenient syntactically to make an extension method out of your Combine method, which would make it available anywhere you go.


All you need is this, for any IEnumerable<IEnumerable<T>> lists :

var combined = lists.Aggregate((l1, l2) => l1.Concat(l2));

This will combine all the items in lists into one IEnumerable<T> (with duplicates). Use Union instead of Concat to remove duplicates, as noted in the other answers.

참고URL : https://stackoverflow.com/questions/4493858/elegant-way-to-combine-multiple-collections-of-elements

반응형