5

2 つのクエリがあり、それぞれがオブジェクトのリストを返します。

List<A> list1 = (....query...)
List<A> list2 = (....query...)

「A」はオブジェクトモデルです。

どちらのクエリもほぼ同じオブジェクトを返しますが、プロパティ セットは異なります。

重複を削除して、オブジェクト A のプロパティに基づいて単一のリストにマージします。

基本的には次のようなものです:

List<A> finalLis = list1 join list2 on elemList1.somePropID == elemList2.somePropID 

シンプルな C# スタイルでは、次のようになります。

foreach(elem1 : list1) {
    foreach(elem2: list1) {
       if(elem1.someID == elem2.someID) {
           elem1.someProp = elem2.someProp
           elem1.otherProp = elem2.otherProp
        }
     }
}

linqにはもっとエレガントな方法があると確信しているので、私はこのようにしたくありません。

何か提案があれば教えてください。

4

5 に答える 5

1

Linq は、選択には役立ちますが、更新には役立ちません。foreachしたがって、ステートメントを取り除くことはありません。したがって、タスクは linq で次のように記述できます。

//the query is like LEFT JOIN in SQL
var query = from x in list1
            join y in list2 on x.IDItem equals y.IDItem
            into z
            from q in z.DefaultIfEmpty()
            select new {IOne = x, ITwo = q};
foreach (var pair in query)
{
    if (pair.ITwo != null) // && pair.IOne.OneProperty != null
        pair.IOne.OneProperty = pair.ITwo.TwoProperty;
}

var resultList = query.Select(x => x.IOne).ToList();

結果はこちらで確認できます。

于 2013-01-16T17:44:56.923 に答える
0

これを試して:

List<A> list = (from e1 in list1
           join e2 in list2
           on e1.ID equals e2.ID
           select new A
           {
              ID = l2.ID,
              someProp1 = l2.someProp1,
              someProp2 = l2.someProp2
           }).ToList();

次に、すべての要素を含む3番目のリストが作成されます。

このリンクが役立つ場合があります:LINQ Join 2 List <T> s

于 2013-01-16T15:21:15.217 に答える
0

Linq はクエリ用であり、更新用ではありません。結合を単純化できますが、更新を行うためにループする必要があります。

何かのようなもの:

List<A> finalList = 
   from item1 in list1 
   join item2 in list2 on item1.somePropID equals item2.somePropID 
   select new{Item1 = item1, Item2 = item2};

foreach(var item in finalList)
{
    item.Item2.someProp1 = item.Item1.someProp1;
    item.Item2.someProp2 = item.Item1.someProp2;
}
于 2013-01-16T15:33:50.483 に答える
0

リストをソートする必要があるため、すべてのソリューションList<T>はせいぜい N * Log(n) で実行されます。

モデルに等価メンバーを実装し、HashSet<T>代わりに a を使用します。

これは、複雑さと割り当ての両方で最適です。

var set1 = new HashSet<Model>
{
    new Model(0, "000"),
    new Model(2, "222"),
    new Model(4, "444"),
};

var set2 = new HashSet<Model>
{
    new Model(1, "111"),
    new Model(2, "2222"),
    new Model(3, "333"),
};

set1.ExceptWith(set2);
set1.UnionWith(set2);

追加するには、結果セットとして上書きセットを使用する方が高速です。

set2.UnionWith(set1);

Model上記のサンプルのクラス:

class Model
{
    public readonly int Id;
    public string Data;

    public Model(int id, string data)
    {
        Id = id;
        Data = data;
    }

    public override int GetHashCode()
    {
        return Id;
    }

    protected bool Equals(Model other)
    {
        return Id == other.Id;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        return obj.GetType() == GetType() && Equals((Model) obj);
    }
}
于 2015-08-09T16:31:56.990 に答える
0

LINQを使いたいと思うのは当然です。

ここでの回答は、スニペットが非常に非効率的であり、list1.Length * list2.Length 操作が発生することを除けば、指定された C# スニペットとすべて同等です。

LINQ 結合を使用すると、はるかに効率的で、おおよそ list1.Length + list2.Length 操作になります。

これは、id の結合が辞書を使用してこのようなことを行うためです。

// create a dict so that you can lookup things in item1 based on id
var list1IdToADict = list1.ToDictionary(a => a.id);

//filter out things not in both lists (join on there id)
var joinedList2 = list2.Where(a => list1IdToADict.ContainsKey(a.id)); 

他の答えはよりエレガントですが、この方法でやりたい場合は、で終了できます

foreach(var a in joinedList2){
    a.someProp = list1IdToADict[a.id].someProp;
    a.otherProp = list1IdToADict[a.id].otherProp;
}
于 2013-02-12T09:27:37.993 に答える