问题
There are loads of ways to find to find Duplicates in a list, is There any way to find continuous duplicates in a List.
For example
List<string> stringList = new List<string>();
stringList.Add("Name1");
stringList.Add("Name2");
stringList.Add("Name1");
Shouldn't find any but
stringList.Add("Name1");
stringList.Add("Name1");
stringList.Add("Name2");
Should return 1 Entry
This returns duplicates.
var q = listString.GroupBy(x => x)
.Select(g => new { Value = g.Key, Count = g.Count() })
.OrderByDescending(x => x.Count);
回答1:
Why not just store the last item? Something like this
public static partial class EnumerableExtensions {
// Simplest; IEquatable<T> for advanced version
public static IEnumerable<T> Continuous<T>(this IEnumerable<T> source) {
if (null == source)
throw new ArgumentNullException("source");
T lastItem = default(T);
Boolean first = true;
foreach (var item in source) {
if (first) {
lastItem = item;
first = false;
}
else if (Object.Equals(item, lastItem))
yield return item;
else
lastItem = item;
}
}
}
And then
List<string> stringList = new List<string>() {
"Name1",
"Name1",
"Name2",
};
var contDups = stringList
.Continuous()
.ToList();
回答2:
Here is one way to do it that returns the duplicate items and their indexes:
var duplicates =
stringList
.Select((x,i) => new {Item = x, Index = i})
.Skip(1) //We start with the second item
.Where(y => y.Item == stringList[y.Index-1])
.ToList();
回答3:
Since you asked "If we can get which item is duplicate and starting index and number of occurrences", here's a solution to that particular requirement.
This outputs the following:
2 was repeated 2 times starting at index 1
3 was repeated 3 times starting at index 4
4 was repeated 4 times starting at index 8
Here's the code:
using System;
using System.Collections.Generic;
namespace Demo
{
class DupeInfo
{
public string Text;
public int Index;
public int Count;
}
static class Program
{
static void Main()
{
var test = new[]
{
"1",
"2", "2",
"A",
"3", "3", "3",
"B",
"4", "4", "4", "4",
"C",
};
foreach (var dupeinfo in FindRepeats(test))
Console.WriteLine($"{dupeinfo.Text} was repeated {dupeinfo.Count} times starting at index {dupeinfo.Index}");
}
public static IEnumerable<DupeInfo> FindRepeats(IEnumerable<string> input)
{
int i = 0;
int j = 0;
int c = -1;
string prev = null;
foreach (var curr in input)
{
if (curr != prev)
{
if (c >= 0)
yield return new DupeInfo {Text = prev, Count = c + 2, Index = j};
c = -1;
j = i;
}
else
{
++c;
}
prev = curr;
++i;
}
if (c >= 0)
yield return new DupeInfo {Text = prev, Count = c + 2, Index = j};
}
}
}
回答4:
You can start from defining what it means for an item to be a "consecutive duplicate":
An item at position
i
is a consecutive duplicate if it is the same as the item at positioni-1
One way to compare a value with another value in a prior position is to use Zip
with a list "shifted over" by one element:
var consecutiveDuplicates = list.Skip(1)
.Zip(list, (me, prior) => new {ThisItem = me, Prior = prior})
.Where(p => p.ThisItem == p.Prior)
.Select(p => p.ThisItem) // Both sides are equal, pick either one
.ToList();
list.Skip(1).Zip(list,...)
expression combines the list with itself with a shift of 1, so you can get this element and its prior element for N-1 positions where prior element is defined. The rest is a straightforward translation of English definition into LINQ statements
来源:https://stackoverflow.com/questions/36935592/find-continuous-duplicates-in-a-list