Küçük bir bayt listem var ve hepsinin farklı değerler olup olmadığını test etmek istiyorum. Örneğin, şuna sahibim:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
Tüm değerlerin farklı olup olmadığını kontrol etmenin en iyi yolu nedir?
Küçük bir bayt listem var ve hepsinin farklı değerler olup olmadığını test etmek istiyorum. Örneğin, şuna sahibim:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
Tüm değerlerin farklı olup olmadığını kontrol etmenin en iyi yolu nedir?
Yanıtlar:
bool isUnique = theList.Distinct().Count() == theList.Count();
İşte Enumerable.Distinct+ ' dan daha verimli olan başka bir yaklaşım Enumerable.Count(dizi bir koleksiyon türü değilse de daha fazlası). Bu bir kullanır HashSet<T>çiftleri ortadan kaldıran aramalarını çok verimli ve bir sayım-özelliği vardır:
var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;
veya başka - daha incelikli ve verimli - yaklaşım:
var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);
HashSet<T>.Addfalseöğe zaten içinde olduğu için eklenemezse döndürür HashSet. Enumerable.Allilk "yanlış" üzerinde durur.
Assert.IsTrue(samples.Add(AwesomeClass.GetUnique()));. Onlar ve onlar :) Senin için +1 Tim :)
bool allDifferent = theList.All(s => diffChecker.Add(s))
List.All(HashSet.Add)) neredeyse her durumda diğer ikisinden çok daha hızlı görünüyor
Tamam, işte standart .Net kullanmayı düşünebildiğim en verimli yöntem.
using System;
using System.Collections.Generic;
public static class Extension
{
public static bool HasDuplicate<T>(
this IEnumerable<T> source,
out T firstDuplicate)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var checkBuffer = new HashSet<T>();
foreach (var t in source)
{
if (checkBuffer.Add(t))
{
continue;
}
firstDuplicate = t;
return true;
}
firstDuplicate = default(T);
return false;
}
}
esasen, tek yapmak istediğiniz ilk kopyayı bulmaksa, tüm diziyi iki kez numaralandırmanın amacı nedir?
Bunu, boş ve tek bir öğe dizilerini özel olarak muhafaza ederek daha fazla optimize edebilirdim, ancak bu, minimum kazançla okunabilirlik / sürdürülebilirlikten düşecektir.
sequenceolmalı source). Ancak bunlar düzeltildikten sonra harika çalışıyor
if (!checkBuffer.Add(t)) { firstDuplicate = t; return true }döngü içinde olması gerektiğini düşünüyorum .
DistinctKullanmaya benzer mantık GroupBy:
var isUnique = theList.GroupBy(i => i).Count() == theList.Count;
theList.GroupBy(o => o.SomeProperty).Count() == theList.Count;Distinct () buna izin vermezken , bir özelliğe göre benzersizliği kontrol etmek istiyorsanız bu yararlıdır .
Pek çok çözüm var.
Ve şüphesiz LINQ'nun "juergen d" ve "Tim Schmelter" olarak kullanılmasıyla daha güzel olanlar.
Ancak, "Karmaşıklığı" ve hızı açıklarsanız, en iyi çözüm bunu kendi başınıza uygulamak olacaktır. Çözümlerden biri, N boyutunda bir dizi oluşturmak olacaktır (bayt için 256'dır). Ve diziyi döngüye sokun ve her yinelemede, değer 1 ise eşleşen sayı indeksini test edecek, yani dizi indeksini zaten artırıyorum ve bu nedenle dizi farklı değil, aksi takdirde dizi hücresini artıracağım ve kontrol etmeye devam edeceğim .
Yinelenen değerleri bulmak istiyorsanız başka bir çözüm.
var values = new [] { 9, 7, 2, 6, 7, 3, 8, 2 };
var sorted = values.ToList();
sorted.Sort();
for (var index = 1; index < sorted.Count; index++)
{
var previous = sorted[index - 1];
var current = sorted[index];
if (current == previous)
Console.WriteLine(string.Format("duplicated value: {0}", current));
}
Çıktı:
duplicated value: 2
duplicated value: 7
IEnumerable'ın (aray, list, vb.) Aşağıdaki gibi benzersiz olup olmadığını kontrol ederim:
var isUnique = someObjectsEnum.GroupBy(o => o.SomeProperty).Max(g => g.Count()) == 1;