Sử dụng LINQ, từ a List<int>
, làm cách nào tôi có thể truy xuất danh sách chứa các mục được lặp lại nhiều lần và các giá trị của chúng?
Sử dụng LINQ, từ a List<int>
, làm cách nào tôi có thể truy xuất danh sách chứa các mục được lặp lại nhiều lần và các giá trị của chúng?
Câu trả lời:
Cách dễ nhất để giải quyết vấn đề là nhóm các yếu tố dựa trên giá trị của chúng, sau đó chọn một đại diện của nhóm nếu có nhiều hơn một yếu tố trong nhóm. Trong LINQ, điều này dịch là:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => y.Key)
.ToList();
Nếu bạn muốn biết các yếu tố được lặp lại bao nhiêu lần, bạn có thể sử dụng:
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(y => new { Element = y.Key, Counter = y.Count() })
.ToList();
Điều này sẽ trả về một List
loại ẩn danh và mỗi phần tử sẽ có các thuộc tính Element
và Counter
, để lấy thông tin bạn cần.
Và cuối cùng, nếu đó là một cuốn từ điển bạn đang tìm kiếm, bạn có thể sử dụng
var query = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.ToDictionary(x => x.Key, y => y.Count());
Điều này sẽ trả về một từ điển, với phần tử của bạn là khóa và số lần nó được lặp lại dưới dạng giá trị.
code
for (int i = 0; i <trùng lặp.Count; i ++) {int trùng lặp = trùng lặp [i]; trùng lặpLocation.Add (trùng lặp, Danh sách mới <int> ()); for (int k = 0; k <hitList.Ldrops; k ++) {if (hitList [k] .Contains (trùng lặp)) {trùng lặpLocation.EuityAt (i) .Value.Add (k); }} // loại bỏ trùng lặp theo một số quy tắc. }code
Tìm hiểu xem một liệt kê có chứa bất kỳ bản sao :
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Tìm hiểu xem tất cả các giá trị trong một liệt kê là duy nhất :
var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
Một cách khác là sử dụng HashSet
:
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
Nếu bạn muốn các giá trị duy nhất trong danh sách trùng lặp của bạn:
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();
Đây là giải pháp tương tự như một phương pháp mở rộng chung:
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 }
làm nguồn, kết quả là một IEnumerable<int>
phần tử có giá trị là 1
(trong đó giá trị trùng lặp chính xác là 2)
Console.WriteLine("Count: {0}", duplicates.Count());
trực tiếp bên dưới nó và nó in 6
. Trừ khi tôi thiếu một cái gì đó về các yêu cầu cho chức năng này, chỉ nên có 1 mục trong bộ sưu tập kết quả.
ToList
vào để khắc phục sự cố, nhưng điều đó có nghĩa là phương thức được thực thi ngay khi nó được gọi, chứ không phải khi bạn lặp lại kết quả.
var hash = new HashSet<int>();
var duplicates = list.Where(i => !hash.Add(i));
sẽ dẫn đến một danh sách bao gồm tất cả các lần xuất hiện trùng lặp. Vì vậy, nếu bạn có bốn lần xuất hiện của 2 trong danh sách của mình, thì danh sách trùng lặp của bạn sẽ chứa ba lần xuất hiện của 2, vì chỉ một trong hai lần xuất hiện có thể được thêm vào Hashset. Nếu bạn muốn danh sách của mình chứa các giá trị duy nhất cho mỗi bản sao, thay vào đó hãy sử dụng mã này:var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
Bạn có thể làm được việc này:
var list = new[] {1,2,3,1,4,2};
var duplicateItems = list.Duplicates();
Với các phương thức mở rộng này:
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();
}
}
Sử dụng IsMult Môn () trong phương thức Sao chép nhanh hơn Count () vì điều này không lặp lại toàn bộ bộ sưu tập.
Count()
là tính toán trước và giải pháp của bạn có thể chậm hơn.
Count()
] về cơ bản khác với việc lặp lại toàn bộ danh sách. Count()
được tính toán trước nhưng lặp lại toàn bộ danh sách thì không.
Tôi đã tạo ra một sự mở rộng để đáp ứng với điều này, bạn có thể đưa nó vào các dự án của bạn, tôi nghĩ điều này sẽ trả lại nhiều trường hợp nhất khi bạn tìm kiếm các bản sao trong Danh sách hoặc Linq.
Thí dụ:
//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
*/
}
Để chỉ tìm các giá trị trùng lặp:
var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);
Ví dụ. danh sách var = new [] {1,2,3,1,4,2};
vì vậy nhóm theo sẽ nhóm các số theo các khóa của chúng và sẽ duy trì số đếm (số lần lặp lại) với nó. Sau đó, chúng tôi chỉ kiểm tra các giá trị đã lặp lại nhiều lần.
Để tìm các giá trị uniuqe chỉ:
var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);
Ví dụ. danh sách var = new [] {1,2,3,1,4,2};
vì vậy nhóm theo sẽ nhóm các số theo các khóa của chúng và sẽ duy trì số đếm (số lần lặp lại) với nó. Sau đó, chúng tôi chỉ kiểm tra các giá trị đã lặp lại một lần có nghĩa là duy nhất.
var unique = list.Distinct(x => x)
Toàn bộ bộ phần mở rộng Linq to SQL của các chức năng trùng lặp được kiểm tra trong MS SQL Server. Không cần sử dụng .ToList () hoặc IEnumerable. Các truy vấn này thực thi trong SQL Server chứ không phải trong bộ nhớ. . Kết quả chỉ trả về tại bộ nhớ.
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()));
}
Có một câu trả lời nhưng tôi không hiểu tại sao nó không hoạt động;
var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);
giải pháp của tôi là như thế trong tình huống này;
var duplicates = model.list
.GroupBy(s => s.SAME_ID)
.Where(g => g.Count() > 1).Count() > 0;
if(duplicates) {
doSomething();
}