두 목록을 함께 결합


333

string 유형 (또는 다른 유형)의 두 목록이있는 경우 두 목록을 결합하는 빠른 방법은 무엇입니까?

순서는 동일하게 유지되어야합니다. 중복은 제거해야합니다 (두 링크의 모든 항목은 고유하지만). 인터넷 검색을 할 때이 점을 많이 찾지 못했으며 전달 속도를 위해 .NET 인터페이스를 구현하고 싶지 않았습니다.


5
주문이 중요합니까? 중복을 유지 하시겠습니까?
Larsenal

답변:


573

시도해 볼 수 있습니다 :

List<string> a = new List<string>();
List<string> b = new List<string>();

a.AddRange(b);

에 대한 MSDN 페이지 AddRange

이렇게하면 목록의 순서가 유지되지만 중복되는 항목 Union은 제거되지 않습니다 .

이것은 list를 변경합니다 a. 원래 목록을 유지 Concat하려면 다른 답변에서 지적한대로 사용해야합니다 .

var newList = a.Concat(b);

이 다시 표시 IEnumerable장기로는 a널 (null)이 아닙니다.


27
어느 방법을 언제 사용해야할지 아무도 모른다. AddRange는 목록을 편집하여 두 번째 목록을 추가합니다 (.Add (foo)를 여러 번 호출 한 것처럼). Concat 및 Union 확장 방법은 원래 목록을 변경하지 않습니다. 그들은 느리게 새로운 IEnumerable을 구성하고 필요하지 않으면 원래 목록 멤버에도 액세스하지 않습니다. 언급했듯이 Union은 중복을 제거하지만 다른 것들은 제거하지 않습니다.
ShawnFumo 2019 년

4
누구 든지이 방법의 복잡성이 무엇인지 알고 있습니까? Microsoft는이 중요한 정보를 MSDN의 일부로 제공하지 않습니다.
Jacob

2
다양한 접근 방식을 비교해 보는 것이 좋습니다. 또한 다양한 옵션에 대한 성능 분석을 보여줍니다. 병합 컬렉션
BogeyMan

이것은 완벽하게 작동합니다. 50 만 개가 넘는 항목에 concat ()을 사용하고 있었는데 몇 분이 걸렸습니다. 이 방법은 5 초 미만이 소요됩니다.
GreenFerret95

111

최소 공간 오버 헤드가있는 방법은 Concat 확장 방법을 사용하는 것입니다.

var combined = list1.Concat(list2);

IEnumerable<T>list1과 list2의 요소를 순서대로 열거 할 인스턴스를 만듭니다 .


2
기억 using System.Linq;CONCAT을 사용할 수 있도록
tothemario

43

연합 (EU)의 방법은 당신의 요구를 충족 수 있습니다. 주문 또는 복제가 중요한지 여부를 지정하지 않았습니다.

두 개의 IEnumerable을 가져 와서 여기에 표시된 것처럼 합집합을 수행하십시오.

int[] ints1 = { 5, 3, 9, 7, 5, 9, 3, 7 };
int[] ints2 = { 8, 3, 6, 4, 4, 9, 1, 0 };

IEnumerable<int> union = ints1.Union(ints2);

// yields { 5, 3, 9, 7, 8, 6, 4, 1, 0 } 

24

이 같은:

firstList.AddRange (secondList);

또는 System.Linq에 정의 된 'Union'확장 방법을 사용할 수 있습니다. 'Union'을 사용하면 항목을 통합해야하는지 여부를 지정하는 데 사용할 수있는 비교자를 지정할 수도 있습니다.

이처럼 :

List<int> one = new List<int> { 1, 2, 3, 4, 5 };
List<int> second=new List<int> { 1, 2, 5, 6 };

var result = one.Union (second, new EqComparer ());

foreach( int x in result )
{
    Console.WriteLine (x);
}
Console.ReadLine ();

#region IEqualityComparer<int> Members
public class EqComparer : IEqualityComparer<int>
{
    public bool Equals( int x, int y )
    {
        return x == y;
    }

    public int GetHashCode( int obj )
    {
        return obj.GetHashCode ();
    }
}
#endregion

17
targetList = list1.Concat(list2).ToList();

잘 작동하고 있다고 생각합니다. 앞서 언급했듯이 Concat은 새로운 시퀀스를 반환하고 결과를 List로 변환하는 동안 완벽하게 작동합니다. AddRange 메서드를 사용할 때 암시 적 변환이 실패 할 수 있습니다.


13

목록에 일부 항목이 있으면 사용할 수 있습니다

var all = list1.Concat(list2).Concat(list3) ... Concat(listN).Distinct().ToList();

7

그것들이 같은 타입이라면 AddRange를 사용하면 매우 간단합니다 :

list2.AddRange(list1);

7
var bigList = new List<int> { 1, 2, 3 }
    .Concat(new List<int> { 4, 5, 6 })
    .ToList(); /// yields { 1, 2, 3, 4, 5, 6 }

나도 이것을 좋아한다. 매우 간단합니다. 감사.
GurdeepS

목록을 변경하지 않기 때문에 이것을 좋아합니다.
Ev.


4
List<string> list1 = new List<string>();
list1.Add("dot");
list1.Add("net");

List<string> list2 = new List<string>();
list2.Add("pearls");
list2.Add("!");

var result = list1.Concat(list2);


2

한 가지 방법으로, 특히 각 요소를 어떤 식 으로든 변경하려는 경우 (예를 들어 .Trim()모든 요소를 원할 경우) 좀 더 강력 할 수 있다고 언급하지 않았습니다 .

List<string> a = new List<string>();
List<string> b = new List<string>();
// ...
b.ForEach(x=>a.Add(x.Trim()));

1

링크를보십시오

public class ProductA
{ 
public string Name { get; set; }
public int Code { get; set; }
}

public class ProductComparer : IEqualityComparer<ProductA>
{

public bool Equals(ProductA x, ProductA y)
{
    //Check whether the objects are the same object. 
    if (Object.ReferenceEquals(x, y)) return true;

    //Check whether the products' properties are equal. 
    return x != null && y != null && x.Code.Equals(y.Code) && x.Name.Equals(y.Name);
    }

public int GetHashCode(ProductA obj)
{
    //Get hash code for the Name field if it is not null. 
    int hashProductName = obj.Name == null ? 0 : obj.Name.GetHashCode();

    //Get hash code for the Code field. 
    int hashProductCode = obj.Code.GetHashCode();

    //Calculate the hash code for the product. 
    return hashProductName ^ hashProductCode;
}
}


    ProductA[] store1 = { new ProductA { Name = "apple", Code = 9 }, 
                   new ProductA { Name = "orange", Code = 4 } };

    ProductA[] store2 = { new ProductA { Name = "apple", Code = 9 }, 
                   new ProductA { Name = "lemon", Code = 12 } };

// 중복을 제외하고 두 배열에서 제품을 가져옵니다.

IEnumerable<ProductA> union =
  store1.Union(store2);

foreach (var product in union)
    Console.WriteLine(product.Name + " " + product.Code);

/*
    This code produces the following output:

    apple 9
    orange 4
    lemon 12
*/

1

내가 사용하는 두 가지 옵션은 다음과 같습니다.

list1.AddRange(list2);

또는

list1.Concat(list2);

그러나 AddRange재귀 함수와 함께 메서드를 사용할 때 매우 자주 호출되는 최대 크기에 도달했기 때문에 SystemOutOfMemoryException이 발생했습니다.

(Google 번역 메시지)
배열 크기가 지원되는 범위를 초과했습니다.

를 사용 Concat하여 그 문제 를 해결했습니다.


0

Union참조 유형 객체가 겹치는 컬렉션에서 기본 비교기와의 작동 방식 을 테스트하고 싶었습니다 .

내 목표는 다음과 같습니다

class MyInt
{
    public int val;

    public override string ToString()
    {
        return val.ToString();
    }
}

내 테스트 코드는 다음과 같습니다

MyInt[] myInts1 = new MyInt[10];
MyInt[] myInts2 = new MyInt[10];
int overlapFrom = 4;
Console.WriteLine("overlapFrom: {0}", overlapFrom);

Action<IEnumerable<MyInt>, string> printMyInts = (myInts, myIntsName) => Console.WriteLine("{2} ({0}): {1}", myInts.Count(), string.Join(" ", myInts), myIntsName);

for (int i = 0; i < myInts1.Length; i++)
    myInts1[i] = new MyInt { val = i };
printMyInts(myInts1, nameof(myInts1));

int j = 0;
for (; j + overlapFrom < myInts1.Length; j++)
    myInts2[j] = myInts1[j + overlapFrom];
for (; j < myInts2.Length; j++)
    myInts2[j] = new MyInt { val = j + overlapFrom };
printMyInts(myInts2, nameof(myInts2));

IEnumerable<MyInt> myUnion = myInts1.Union(myInts2);
printMyInts(myUnion, nameof(myUnion));

for (int i = 0; i < myInts2.Length; i++)
    myInts2[i].val += 10;
printMyInts(myInts2, nameof(myInts2));
printMyInts(myUnion, nameof(myUnion));

for (int i = 0; i < myInts1.Length; i++)
    myInts1[i].val = i;
printMyInts(myInts1, nameof(myInts1));
printMyInts(myUnion, nameof(myUnion));

출력은 다음과 같습니다.

overlapFrom: 4
myInts1 (10): 0 1 2 3 4 5 6 7 8 9
myInts2 (10): 4 5 6 7 8 9 10 11 12 13
myUnion (14): 0 1 2 3 4 5 6 7 8 9 10 11 12 13
myInts2 (10): 14 15 16 17 18 19 20 21 22 23
myUnion (14): 0 1 2 3 14 15 16 17 18 19 20 21 22 23
myInts1 (10): 0 1 2 3 4 5 6 7 8 9
myUnion (14): 0 1 2 3 4 5 6 7 8 9 20 21 22 23

따라서 모든 것이 잘 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.