2つのリストを結合する


333

文字列型(またはその他の型)の2つのリストがある場合、2つのリストを結合する簡単な方法は何ですか?

順序は変わらないはずです。重複は削除する必要があります(ただし、両方のリンクのすべてのアイテムは一意です)。私はグーグルでこれについて多くを見つけることができず、配信の速度のために.NETインターフェイスを実装したくありませんでした。


5
順序は重要ですか?重複を保持しますか?
ラルセナル2009年

回答:


572

あなたは試すことができます:

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

a.AddRange(b);

MSDNページ AddRange

これによりリストの順序は保持されますが、重複するものUnionは削除されません。

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

var newList = a.Concat(b);

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


27
どの方法をいつ使用するかについては、誰も詳しく知りません。AddRangeはリストを編集し、2番目のリストを追加します(まるで.Add(foo)を何度も呼び出したかのように)。ConcatおよびUnion拡張メソッドは、元のリストを変更しません。彼らは遅延して新しいIEnumerableを作成し、必要でない限り元のリストメンバーにアクセスすることもしません。前述のとおり、Unionは重複を削除しますが、他は削除しません。
ShawnFumo 2015年

4
誰もがこの方法の複雑さを知っていますか?(MicrosoftがMSDNの一部としてこの重要な情報を提供しないのは残念です)
Jacob

2
彼のさまざまなアプローチのこの良い比較を確認することをお勧めします。また、さまざまなオプションのパフォーマンス分析をいくつか示します。コレクションのマージ
BogeyMan

これは完全に機能します。50万以上のアイテムでconcat()を使用しており、数分かかりました。このアプローチは5秒未満かかります。
GreenFerret95

110

スペースのオーバーヘッドを最小限に抑える方法は、Concat拡張メソッドを使用することです。

var combined = list1.Concat(list2);

IEnumerable<T>list1とlist2の要素をこの順序で列挙するインスタンスを作成します。


2
using System.Linq;Concatを使用できることを忘れないでください
tothemario

43

連合の方法は、あなたのニーズに対応することがあります。順序または重複が重要かどうかは指定しませんでした。

2つの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、2009年

どちらのリストも変更しないため、これが好きです。
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

1つの方法として、特に各要素を何らかの方法で変更したい場合(たとえば、.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

私が使用する2つのオプションは次のとおりです。

list1.AddRange(list2);

または

list1.Concat(list2);

ただし、AddRangeメソッドを再帰関数で使用すると、それ自体を頻繁に呼び出すことに気づきました。ディメンションの最大数に達したため、SystemOutOfMemoryExceptionが発生しました。

(メッセージGoogle Translated)
配列の次元がサポートされている範囲を超えました。

を使用し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.