リストがあります
List<MyObject> myList
リストにアイテムを追加していますが、そのオブジェクトが既にリストにあるかどうかを確認したいと思います。
だから私はこれを行う前に:
myList.Add(nextObject);
NextObjectが既にリストにあるかどうかを確認したい。
オブジェクト「MyObject」には多くのプロパティがありますが、比較は2つのプロパティの一致に基づいています。
この「MyObject」のリストに新しい「MyObject」を追加する前にチェックを行う最善の方法は何ですか。
私が考えた唯一の解決策は、リストから辞書に変更してから、キーをプロパティの連結文字列にすることでした(これは少し違法なようです)。
リストやLINQなどを使用した他のクリーナーソリューションはありますか?
特定の状況のニーズによって異なります。たとえば、辞書アプローチは次の場合に非常に適しています。
上記に当てはまらない場合は、Any()
:を使用してください
Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);'
これは、一致が見つかるまで、または最後に達するまでリストを列挙します。
含む メソッドを使用します。等式関数Equals
に基づいて機能することに注意してください
bool alreadyExist = list.Contains(item);
これらの2つのプロパティを使用して保守できる場合、次のことができます。
bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");
この場合、リストが必要ですか?リストに多数の項目を追加している場合、myList.Contains
またはmyList.Any
;でパフォーマンスが低下します。ランタイムは2次になります。より良いデータ構造の使用を検討することをお勧めします。例えば、
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class MyClassComparer : EqualityComparer<MyClass>
{
public override bool Equals(MyClass x, MyClass y)
{
if(x == null || y == null)
return x == y;
return x.Property1 == y.Property1 && x.Property2 == y.Property2;
}
public override int GetHashCode(MyClass obj)
{
return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
}
}
HashSetは次の方法で使用できます。
var set = new HashSet<MyClass>(new MyClassComparer());
foreach(var myClass in ...)
set.Add(myClass);
もちろん、MyClass
の平等のこの定義が「ユニバーサル」である場合、IEqualityComparer
実装を記述する必要はありません。クラス自体のGetHashCode
とEquals
をオーバーライドするだけで済みます。
言及する別のポイントは、平等関数が期待どおりであることを確認する必要があるということです。 equalsメソッドをオーバーライドして、2つのインスタンスが等しいと見なされるためにオブジェクトのどのプロパティを一致させる必要があるかを設定する必要があります。
次に、mylist.contains(item)を実行します。
編集:私は最初に言った:
ディクショナリソリューションの洗練されていないもの。辞書の作成時にコンパレーターを設定するだけでよいので、特に私には完璧に思えます。
もちろん、それが値でもあるときに何かをキーとして使用することは洗練されていません。
したがって、HashSetを使用します。後の操作でインデックス作成が必要な場合は、追加が完了したときにリストからリストを作成します。それ以外の場合は、ハッシュセットを使用します。
以下は、問題を解決する方法の概念を示すクイックコンソールアプリです。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
public class myobj
{
private string a = string.Empty;
private string b = string.Empty;
public myobj(string a, string b)
{
this.a = a;
this.b = b;
}
public string A
{
get
{
return a;
}
}
public string B
{
get
{
return b;
}
}
}
class Program
{
static void Main(string[] args)
{
List<myobj> list = new List<myobj>();
myobj[] objects = { new myobj("a", "b"), new myobj("c", "d"), new myobj("a", "b") };
for (int i = 0; i < objects.Length; i++)
{
if (!list.Exists((delegate(myobj x) { return (string.Equals(x.A, objects[i].A) && string.Equals(x.B, objects[i].B)) ? true : false; })))
{
list.Add(objects[i]);
}
}
}
}
}
楽しい!
シンプルだが機能する
MyList.Remove(nextObject)
MyList.Add(nextObject)
または
if (!MyList.Contains(nextObject))
MyList.Add(nextObject);