2009-10-06 12 views
220

2つのタイプの文字列(または他のタイプ)のリストが2つある場合、2つのリストを簡単に結合する方法は何ですか?2つのリストをまとめて結合する

注文は同じである必要があります。重複は削除する必要があります(ただし、両方のリンクのすべての項目は一意です)。私はグーグルでこれについて多くは見つけられず、配信速度のために.NETインターフェイスを実装したくなかった。このような

+4

注文には問題がありますか?重複を保持しますか? – Larsenal

+1

* [どのようにC#でリストを連結しますか?](http://stackoverflow.com/questions/1042219/how-do-you-concatenate-lists-in-c)*の重複が考えられます。 –

答えて

380

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

a.AddRange(b); 

MSDN page for AddRange

これは、リストの順番を維持するが、それはUnionはどうしたら任意の重複を削除しません。 。

これは変更リストaです。あなたは、元のリストを維持したいならば、あなたはConcat(他の回答で指摘したように)を使用する必要があります

var newList = a.Concat(b); 

をこれは限りaがnullではないようIEnumerableを返します。

+13

誰がどのメソッドを使用するかは本当にありません。 AddRangeはリストを編集し、2番目のリストを追加します(あたかも.Add(foo)を呼び出したかのように)。 ConcatおよびUnion拡張メソッドは元のリストを変更しません。彼らは遅れて新しいIEnumerableを構築し、必要がない限り元のリストメンバーにアクセスしません。前述のように、Unionは重複を削除しますが、重複は削除しません。 – ShawnFumo

+2

リストの1つがヌルの場合、 'concat'は機能しません – Amit

+3

誰もがこのメソッドの複雑さを知っていますか? (MicrosoftがMSDNの一環としてこの重要な情報を提供していないことは残念です) – Jacob

19

何か:

firstList.AddRange (secondList); 

それとも、あなたはSystem.Linqの中で定義されている「連合拡張メソッドを使用することができます。 '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 
34

Unionという方法が必要になる場合があります。順序や重複が重要かどうかは指定していません。

2 IEnumerablesを取り、ここに見られるように労働組合を実行します。

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

片道:List.AddRange()種類に応じて?

85

少なくともスペースオーバーヘッドでの方法は、連結拡張メソッドを使用することです。

var combined = list1.Concat(list2); 

そのためにLIST1とLIST2の要素を列挙するIEnumerable<T>のインスタンスを作成します。

7

限り、彼らは同じタイプのものであるとして、それはAddRangeと非常に簡単です:

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

私もこれが好きです。非常に簡単です。ありがとう。 – dotnetdev

+0

いずれかのリストを変更しないので、私はこれが好きです。 –

10

いくつかの項目(s)が両方のリストに存在する場合は、

var all = list1.Concat(list2).Concat(list3) ... Concat(listN).Distinct().ToList(); 
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); 
を使用することができます
12
targetList = list1.Concat(list2).ToList(); 

私はそう思います。前述のように、Concatは新しいシーケンスを返し、結果をListに変換している間、完全にその仕事をします。暗黙的な変換は、AddRangeメソッドを使用するときに失敗することがあります。

1

このlink

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 
*/ 
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 

、すべてが正常に動作します。

関連する問題