LINQ kullanarak a'dan List<int>
birden çok kez tekrarlanan girdileri ve değerlerini içeren bir listeyi nasıl alabilirim?
LINQ kullanarak a'dan List<int>
birden çok kez tekrarlanan girdileri ve değerlerini içeren bir listeyi nasıl alabilirim?
Yanıtlar:
Sorunu çözmenin en kolay yolu, öğeleri değerlerine göre gruplandırmak ve sonra grupta birden fazla öğe varsa grubun bir temsilcisini seçmektir. LINQ'da bu şu anlama gelir:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
Elemanların kaç kez tekrarlandığını bilmek istiyorsanız, şunları kullanabilirsiniz:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
Bu, List
anonim türden bir a döndürür ve her öğe, ihtiyacınız olan bilgileri almak için Element
ve özelliklerine sahip olacaktır Counter
.
Ve son olarak, eğer aradığınız bir sözlükse,
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
Bu, öğeniz anahtar olarak ve kaç kez değer olarak tekrarlandığıyla bir sözlük döndürür.
code
for (int i = 0; i <duplicates.Count; i ++) {int duplicate = duplicates [i]; duplicatesLocation.Add (yinelenen, yeni Liste <int> ()); for (int k = 0; k <hitsList.Length; k ++) {if (hitsList [k]. içerir (kopya)) {duplicatesLocation.ElementAt (i) .Value.Add (k); }} // kopyaları bazı kurallara göre kaldırın. }code
Bir numaralandırılabilir herhangi bir kopya içerip içermediğini öğrenin :
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Numaralandırılabilir bir değerdeki tüm değerlerin benzersiz olup olmadığını öğrenin :
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
Başka bir yol kullanmak HashSet
:
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
Yinelenen listenizde benzersiz değerler istiyorsanız:
var myhash = new HashSet<int>();
var mylist = new List<int>(){1,1,2,2,3,3,3,4,4,4};
var duplicates = mylist.Where(item => !myhash.Add(item)).Distinct().ToList();
İşte genel bir uzantı yöntemi ile aynı çözüm:
public static class Extensions
{
public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)
{
var hash = new HashSet<TKey>(comparer);
return source.Where(item => !hash.Add(selector(item))).ToList();
}
public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
return source.GetDuplicates(x => x, comparer);
}
public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
return source.GetDuplicates(selector, null);
}
public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source)
{
return source.GetDuplicates(x => x, null);
}
}
List<int> { 1, 2, 3, 4, 5, 2 }
Kaynak olarak kullanıldığında sonuç, (doğru yinelenen değer 2 olduğunda) değerine IEnumerable<int>
sahip bir öğeye sahip olur1
Console.WriteLine("Count: {0}", duplicates.Count());
doğrudan altına ekledim ve basıyor 6
. Bu işleve ilişkin gereksinimlerle ilgili bir şey eksik olmadıkça, ortaya çıkan koleksiyonda yalnızca 1 öğe olmalıdır.
ToList
Sorunu düzeltmek için ekledim , ancak sonuçların üzerinde yinelediğinizde değil, yöntemin en kısa sürede yürütüldüğü anlamına gelir.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
tüm kopyaları içeren bir listeye yönlendirir. Bu nedenle, listenizde dört kez 2 tekrarınız varsa, yinelenen listeniz 2'den üç kez içerecektir, çünkü 2'den yalnızca biri HashSet'e eklenebilir. Listenizin her bir kopya için benzersiz değerler içermesini istiyorsanız bunun yerine şu kodu kullanın:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
Bunu yapabilirsiniz:
var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();
Bu genişletme yöntemleriyle:
public static class Extensions
{
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
var grouped = source.GroupBy(selector);
var moreThan1 = grouped.Where(i => i.IsMultiple());
return moreThan1.SelectMany(i => i);
}
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source)
{
return source.Duplicates(i => i);
}
public static bool IsMultiple<T>(this IEnumerable<T> source)
{
var enumerator = source.GetEnumerator();
return enumerator.MoveNext() && enumerator.MoveNext();
}
}
Duplicates yönteminde IsMultiple () yöntemini kullanmak Count () yönteminden daha hızlıdır, çünkü bu işlem tüm koleksiyonu yinelemez.
Count()
edilir bilgisayarlı ve çözüm olasılıkla yavaştır önceden.
Count()
] sayımı temelde tüm listeyi yinelemekten farklıdır. Count()
önceden hesaplanmıştır ancak tüm listeyi yinelemek değildir.
Bunu projelerinize dahil edebileceğiniz bir yanıt uzantısı oluşturdum, List veya Linq'de kopyalar aradığınızda bu durumun en çok geri döndüğünü düşünüyorum.
Misal:
//Dummy class to compare in list
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public Person(int id, string name, string surname)
{
this.Id = id;
this.Name = name;
this.Surname = surname;
}
}
//The extention static class
public static class Extention
{
public static IEnumerable<T> getMoreThanOnceRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
{ //Return only the second and next reptition
return extList
.GroupBy(groupProps)
.SelectMany(z => z.Skip(1)); //Skip the first occur and return all the others that repeats
}
public static IEnumerable<T> getAllRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
{
//Get All the lines that has repeating
return extList
.GroupBy(groupProps)
.Where(z => z.Count() > 1) //Filter only the distinct one
.SelectMany(z => z);//All in where has to be retuned
}
}
//how to use it:
void DuplicateExample()
{
//Populate List
List<Person> PersonsLst = new List<Person>(){
new Person(1,"Ricardo","Figueiredo"), //fist Duplicate to the example
new Person(2,"Ana","Figueiredo"),
new Person(3,"Ricardo","Figueiredo"),//second Duplicate to the example
new Person(4,"Margarida","Figueiredo"),
new Person(5,"Ricardo","Figueiredo")//third Duplicate to the example
};
Console.WriteLine("All:");
PersonsLst.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* OUTPUT:
All:
1 -> Ricardo Figueiredo
2 -> Ana Figueiredo
3 -> Ricardo Figueiredo
4 -> Margarida Figueiredo
5 -> Ricardo Figueiredo
*/
Console.WriteLine("All lines with repeated data");
PersonsLst.getAllRepeated(z => new { z.Name, z.Surname })
.ToList()
.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* OUTPUT:
All lines with repeated data
1 -> Ricardo Figueiredo
3 -> Ricardo Figueiredo
5 -> Ricardo Figueiredo
*/
Console.WriteLine("Only Repeated more than once");
PersonsLst.getMoreThanOnceRepeated(z => new { z.Name, z.Surname })
.ToList()
.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
/* OUTPUT:
Only Repeated more than once
3 -> Ricardo Figueiredo
5 -> Ricardo Figueiredo
*/
}
Yalnızca yinelenen değerleri bulmak için:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Örneğin. var list = yeni [] {1,2,3,1,4,2};
bu nedenle grupla, sayıları tuşlarına göre gruplayacak ve sayıyı (tekrarlama sayısını) koruyacaktır. Bundan sonra, sadece bir kereden fazla tekrar eden değerleri kontrol ediyoruz.
Yalnızca uniuqe değerlerini bulmak için:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Örneğin. var list = yeni [] {1,2,3,1,4,2};
bu nedenle grupla, sayıları tuşlarına göre gruplayacak ve sayıyı (tekrarlama sayısını) koruyacaktır. Bundan sonra, sadece bir kez tekrarlanan değerleri benzersiz olan kontrol ediyoruz.
var unique = list.Distinct(x => x)
MS SQL Server'da denetlenen Yinelenen işlevlerin Linq - SQL uzantıları kümesi. .ToList () veya IEnumerable kullanmadan. Bu sorgular bellek yerine SQL Server'da yürütülür. . Sonuçlar yalnızca belleğe döner.
public static class Linq2SqlExtensions {
public class CountOfT<T> {
public T Key { get; set; }
public int Count { get; set; }
}
public static IQueryable<TKey> Duplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);
public static IQueryable<TSource> GetDuplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);
public static IQueryable<CountOfT<TKey>> DuplicatesCounts<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT<TKey> { Key = y.Key, Count = y.Count() });
public static IQueryable<Tuple<TKey, int>> DuplicatesCountsAsTuble<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
=> source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
}
bir cevap var ama neden çalışmadığını anlamadım;
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
benim çözümüm bu durumda böyledir;
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}