Menggunakan LINQ, dari a List<int>
, bagaimana saya bisa mengambil daftar yang berisi entri berulang lebih dari sekali dan nilainya?
Menggunakan LINQ, dari a List<int>
, bagaimana saya bisa mengambil daftar yang berisi entri berulang lebih dari sekali dan nilainya?
Jawaban:
Cara termudah untuk menyelesaikan masalah adalah mengelompokkan elemen berdasarkan nilainya, dan kemudian memilih perwakilan grup jika ada lebih dari satu elemen dalam grup. Di LINQ, ini diterjemahkan menjadi:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
Jika Anda ingin tahu berapa kali elemen diulang, Anda dapat menggunakan:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
Ini akan List
menghasilkan tipe anonim, dan setiap elemen akan memiliki properti Element
danCounter
, untuk mengambil informasi yang Anda butuhkan.
Dan terakhir, jika kamus yang Anda cari, Anda dapat menggunakannya
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
Ini akan mengembalikan kamus, dengan elemen Anda sebagai kunci, dan berapa kali itu diulang sebagai nilai.
code
for (int i = 0; i <duplicates.Count; i ++) {int duplikat = duplikat [i]; duplicatesLocation.Add (duplikat, Daftar baru <int> ()); for (int k = 0; k <hitsList.Length; k ++) {if (hitsList [k] .Berisi (duplikat)) {duplicatesLocation.ElementAt (i) .Value.Add (k); }} // menghapus duplikat sesuai dengan beberapa aturan. }code
Cari tahu apakah enumerable berisi duplikat :
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Cari tahu apakah semua nilai dalam enumerable unik :
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
Cara lain menggunakan HashSet
:
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
Jika Anda ingin nilai unik dalam daftar duplikat Anda:
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();
Berikut adalah solusi yang sama dengan metode ekstensi generik:
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 }
sebagai sumber, hasilnya adalah IEnumerable<int>
dengan satu elemen memiliki nilai 1
(di mana nilai duplikat yang benar adalah 2)
Console.WriteLine("Count: {0}", duplicates.Count());
tepat di bawahnya dan itu mencetak 6
. Kecuali saya kehilangan sesuatu tentang persyaratan untuk fungsi ini, seharusnya hanya ada 1 item dalam koleksi yang dihasilkan.
ToList
untuk memperbaiki masalah ini, tetapi itu berarti bahwa metode ini dieksekusi segera setelah dipanggil, dan bukan ketika Anda mengulangi hasilnya.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
akan mengarah ke daftar yang mencakup semua kejadian duplikat. Jadi, jika Anda memiliki empat kemunculan 2 dalam daftar Anda, maka daftar duplikat Anda akan berisi tiga kemunculan 2, karena hanya satu dari 2 yang dapat ditambahkan ke HashSet. Jika Anda ingin daftar Anda mengandung nilai-nilai unik untuk setiap duplikat, gunakan kode ini sebagai gantinya:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
Kamu bisa melakukan ini:
var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();
Dengan metode ekstensi ini:
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();
}
}
Menggunakan IsMultiple () dalam metode Duplikat lebih cepat daripada Count () karena ini tidak mengulangi seluruh koleksi.
Count()
adalah pra dihitung dan solusi Anda mungkin lebih lambat.
Count()
] pada dasarnya berbeda dari pengulangan seluruh daftar. Count()
sudah dihitung sebelumnya tetapi iterasi seluruh daftar tidak.
Saya membuat ekstensi untuk menanggapi ini Anda bisa memasukkannya ke dalam proyek Anda, saya pikir ini mengembalikan kasus terbanyak ketika Anda mencari duplikat di Daftar atau Linq.
Contoh:
//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
*/
}
Untuk menemukan nilai duplikat saja:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Misalnya. var list = baru [] {1,2,3,1,4,2};
jadi kelompokkan dengan kelompokkan angka dengan kunci mereka dan akan mempertahankan hitungan (berapa kali itu diulang) dengan itu. Setelah itu, kami hanya memeriksa nilai-nilai yang telah diulang lebih dari satu kali.
Untuk menemukan nilai uniuqe saja:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Misalnya. var list = baru [] {1,2,3,1,4,2};
jadi kelompokkan dengan kelompokkan angka dengan kunci mereka dan akan mempertahankan hitungan (berapa kali itu diulang) dengan itu. Setelah itu, kami hanya memeriksa nilai-nilai yang telah diulang hanya sekali berarti unik.
var unique = list.Distinct(x => x)
Set lengkap Linq ke ekstensi SQL fungsi Duplikat diperiksa di MS SQL Server. Tanpa menggunakan .ToList () atau IEnumerable. Kueri ini mengeksekusi di SQL Server daripada di memori. . Hasilnya hanya kembali di memori.
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()));
}
ada jawaban tetapi saya tidak mengerti mengapa tidak bekerja;
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
solusi saya seperti itu dalam situasi ini;
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}