要件:並べ替えられていないリストで、重複が存在するかどうかを判断します。私がこれを行う典型的な方法は、n二乗のネストされたループです。私は他の人がこれをどのように解決するのか疑問に思っています。 Linqにはエレガントで高性能な方法がありますか?ラムダまたは比較演算子を使用する一般的なものはニースです。
何かが足りない場合を除き、Distinct()
を使用して簡単なもので逃げることができます。それはあなたが思いつくかもしれない最も複雑な実装ではないことは確かですが、重複が削除されるかどうかを教えてくれます:
var list = new List<string>();
// Fill the list
if(list.Count != list.Distinct().Count())
{
// Duplicates exist
}
LINQを使用して複製を見つける :の方法に関するEric Whiteの記事によると、
重複を見つける簡単な方法は、識別子でグループ化するクエリを作成し、複数のメンバーを持つグループをフィルタリングすることです。次の例では、4と3が重複していることを知りたいと思います。
int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 }; var duplicates = listOfItems .GroupBy(i => i) .Where(g => g.Count() > 1) .Select(g => g.Key); foreach (var d in duplicates) Console.WriteLine(d); // 4,3
重複がリストの初期に存在する場合に短絡を許可するには、 HashSet<T>
を追加して、その.Add
メソッドの戻り値を確認します。
.Any
を使用することにより、重複が見つかったらすぐに列挙を短絡できます。
C#とVBの両方でのLINQ拡張メソッドは次のとおりです。
public static bool ContainsDuplicates<T>(this IEnumerable<T> enumerable)
{
var knownKeys = new HashSet<T>();
return enumerable.Any(item => !knownKeys.Add(item));
}
<Extension>
Public Function ContainsDuplicates(Of T)(ByVal enumerable As IEnumerable(Of T)) As Boolean
Dim knownKeys As New HashSet(Of T)
Return enumerable.Any(Function(item) Not knownKeys.Add(item))
End Function
注:no重複があるかどうかを確認するには、単にAny
をAll
に変更します
セット内のすべてのアイテムを配置し、セットのカウントがリストのカウントと異なる場合、重複があります。
bool hasDuplicates<T>(List<T> myList) {
var hs = new HashSet<T>();
for (var i = 0; i < myList.Count; ++i) {
if (!hs.Add(myList[i])) return true;
}
return false;
}
すべてのリストを調べる必要がないため、Distinctよりも効率的である必要があります。
IEnumerable.GroupByメソッドを使用できます。
var list = new List<string> {"1", "2","3", "1", "2"};
var hasDuplicates = list.GroupBy(x => x).Any(x => x.Skip(1).Any());
これらの線に沿ったものは比較的単純であり、重複の数を提供します。
var something = new List<string>() { "One", "One", "Two", "Three" };
var dictionary = new Dictionary<string, int>();
something.ForEach(s =>
{
if (dictionary.ContainsKey(s))
{
dictionary[s]++;
}
else
{
dictionary[s] = 1;
}
});
確かではありませんが、これはDistinctの実装に似ていると思います。
整数または適切に順序付けられたセットを使用している場合、O(nlog n)パフォーマンスのためにバイナリツリーを使用します。
または、別のより高速なソート方法を見つけて、すべての値が前の値と異なることを確認します。
IEnumerableにDistinct()拡張メソッドを使用できます
つかいます - Enumerable.Any
with HashSet.Add
のような:
List<string> list = new List<string> {"A", "A", "B", "C", "D"};
HashSet<string> hashSet = new HashSet<string>();
if(list.Any(r => !hashSet.Add(r)))
{
//duplicate exists.
}
HashSet.Add
は、アイテムが既にfalse
に存在する場合、HashSet
を返します。これはリスト全体を反復しません。
Distinct()
ステートメントを使用して、一意のレコードを見つけることができます。次に、次のような元の汎用リストと比較します。
if (dgCoil.ItemsSource.Cast<BLL.Coil>().ToList().Count != dgCoil.ItemsSource.Cast<BLL.Coil>().Select(c => c.CoilNo).Distinct().Count())
{
//Duplicate detected !!
return;
}