LINQ를 사용하여 목록에서 중복 항목을 얻는 방법은 무엇입니까? [복제]
이 질문에는 이미 답변이 있습니다.
- C # LINQ는 목록 7 답변 에서 중복 찾기
나는 List<string>
같은 것을 가지고 있다 :
List<String> list = new List<String>{"6","1","2","4","6","5","1"};
목록의 중복 항목을 새 목록으로 가져와야합니다. 이제 중첩 for
루프를 사용 하여이 작업을 수행하고 있습니다.
결과 list
는를 포함합니다 {"6","1"}
.
LINQ 또는 람다 식을 사용 하여이 작업을 수행 할 아이디어가 있습니까?
var duplicates = lst.GroupBy(s => s)
.SelectMany(grp => grp.Skip(1));
이렇게하면 모든 중복 항목이 반환되므로 소스 목록에서 중복 된 항목 만 알고 싶다면 Distinct
결과 순서에 적용 하거나 Mark Byers에서 제공 한 솔루션을 사용할 수 있습니다 .
이를 수행하는 한 가지 방법이 있습니다.
List<String> duplicates = lst.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
GroupBy
그룹 같은 함께있는 요소, 그리고 Where
단지에만 중복 당신을 떠나, 한 번 나타나는 그 필터링합니다.
다른 옵션이 있습니다.
var list = new List<string> { "6", "1", "2", "4", "6", "5", "1" };
var set = new HashSet<string>();
var duplicates = list.Where(x => !set.Add(x));
나는 그것이 원래의 질문에 대한 답이 아니라는 것을 알고 있지만, 당신은이 문제로 자신을 찾을 수 있습니다.
결과에 모든 중복 항목을 원하면 다음과 같이 작동합니다.
var duplicates = list
.GroupBy( x => x ) // group matching items
.Where( g => g.Skip(1).Any() ) // where the group contains more than one item
.SelectMany( g => g ); // re-expand the groups with more than one item
내 상황에서는 UI에서 오류로 표시 할 수 있도록 모든 복제본이 필요합니다.
OP에 대한 @Lee의 응답을 기반 으로이 확장 방법을 작성했습니다. 참고 , 기본 매개 변수가 사용되었다 (C # 4.0을 필요로). 그러나 C # 3.0에서 오버로드 된 메소드 호출로 충분합니다.
/// <summary>
/// Method that returns all the duplicates (distinct) in the collection.
/// </summary>
/// <typeparam name="T">The type of the collection.</typeparam>
/// <param name="source">The source collection to detect for duplicates</param>
/// <param name="distinct">Specify <b>true</b> to only return distinct elements.</param>
/// <returns>A distinct list of duplicates found in the source collection.</returns>
/// <remarks>This is an extension method to IEnumerable<T></remarks>
public static IEnumerable<T> Duplicates<T>
(this IEnumerable<T> source, bool distinct = true)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
// select the elements that are repeated
IEnumerable<T> result = source.GroupBy(a => a).SelectMany(a => a.Skip(1));
// distinct?
if (distinct == true)
{
// deferred execution helps us here
result = result.Distinct();
}
return result;
}
이 도움이되기를 바랍니다.
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);
List<String> list = new List<String> { "6", "1", "2", "4", "6", "5", "1" };
var q = from s in list
group s by s into g
where g.Count() > 1
select g.First();
foreach (var item in q)
{
Console.WriteLine(item);
}
I was trying to solve the same with a list of objects and was having issues because I was trying to repack the list of groups into the original list. So I came up with looping through the groups to repack the original List with items that have duplicates.
public List<MediaFileInfo> GetDuplicatePictures()
{
List<MediaFileInfo> dupes = new List<MediaFileInfo>();
var grpDupes = from f in _fileRepo
group f by f.Length into grps
where grps.Count() >1
select grps;
foreach (var item in grpDupes)
{
foreach (var thing in item)
{
dupes.Add(thing);
}
}
return dupes;
}
All mentioned solutions until now perform a GroupBy. Even if I only need the first Duplicate all elements of the collections are enumerated at least once.
The following extension function stops enumerating as soon as a duplicate has been found. It continues if a next duplicate is requested.
As always in LINQ there are two versions, one with IEqualityComparer and one without it.
public static IEnumerable<TSource> ExtractDuplicates(this IEnumerable<TSource> source)
{
return source.ExtractDuplicates(null);
}
public static IEnumerable<TSource> ExtractDuplicates(this IEnumerable<TSource source,
IEqualityComparer<TSource> comparer);
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (comparer == null)
comparer = EqualityCompare<TSource>.Default;
HashSet<TSource> foundElements = new HashSet<TSource>(comparer);
foreach (TSource sourceItem in source)
{
if (!foundElements.Contains(sourceItem))
{ // we've not seen this sourceItem before. Add to the foundElements
foundElements.Add(sourceItem);
}
else
{ // we've seen this item before. It is a duplicate!
yield return sourceItem;
}
}
}
Usage:
IEnumerable<MyClass> myObjects = ...
// check if has duplicates:
bool hasDuplicates = myObjects.ExtractDuplicates().Any();
// or find the first three duplicates:
IEnumerable<MyClass> first3Duplicates = myObjects.ExtractDuplicates().Take(3)
// or find the first 5 duplicates that have a Name = "MyName"
IEnumerable<MyClass> myNameDuplicates = myObjects.ExtractDuplicates()
.Where(duplicate => duplicate.Name == "MyName")
.Take(5);
For all these linq statements the collection is only parsed until the requested items are found. The rest of the sequence is not interpreted.
IMHO that is an efficiency boost to consider.
참고URL : https://stackoverflow.com/questions/3811464/how-to-get-duplicate-items-from-a-list-using-linq
'development' 카테고리의 다른 글
UITextField의 초기 키보드 애니메이션에서 슈퍼 느린 지연 / 지연 (0) | 2020.05.26 |
---|---|
Angular.js 지시문 동적 templateURL (0) | 2020.05.26 |
JavaScript : 클라이언트 측과 서버 측 유효성 검사 (0) | 2020.05.26 |
스토리 보드-식별자가있는 뷰 컨트롤러를 포함하지 않습니다 (0) | 2020.05.26 |
SQL RANK () 대 ROW_NUMBER () (0) | 2020.05.26 |