计算列表中的重复数字

时间:2010-10-01 13:01:23

标签: c# list

我有一个清单:

int list = { 1,1,2,3,4,4,5,7,7,7,10};

现在我需要制作一个计算双数的程序。当前面的数字相同时,数字是两倍。我希望你明白。因此1是双倍,4是双打,我们在7,7,7中得到2双。

7 个答案:

答案 0 :(得分:26)

以下是LINQ的解决方案:

var doubles = list.Skip(1)
                  .Where((number, index) => list[index] == number);

这将通过跳过列表的第一个成员来创建另一个序列,然后查找具有相同索引和相同值的两个序列中的元素。它将以线性时间运行,但仅限于列表通过索引提供O(1)访问权限。

答案 1 :(得分:7)

这是一种相对简单的方法,只在序列上迭代一次,并且可以处理任何序列(不仅仅是列表):

public IEnumerable<T> FindConsecutiveDuplicates<T>(this IEnumerable<T> source)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        T current = iterator.Current;
        while (iterator.MoveNext())
        {
            if (EqualityComparer<T>.Default.Equals(current, iterator.Current))
            {
                yield return current;
            }
            current = iterator.Current;
        }
    }
}

这是另一个更简单的一点,因为它只是一个LINQ查询,但它在Where子句中使用了副作用,这是令人讨厌的:

IEnumerable<int> sequence = ...;

bool first = true;
int current = 0;
var result = sequence.Where(x => {
   bool result = !first && x == current;
   current = x;
   first = false;
   return result;
});

第三种选择,虽然比较清晰,但使用的SelectConsecutive方法基本上是来自this answerSelectPairs,但重命名为稍微清晰一点:)

IEnumerable<int> sequence = ...;
IEnumerable<int> result = sequence.SelectConsecutive((x, y) => new { x, y })
                                  .Where(z => z.x == z.y);

答案 2 :(得分:6)

每个人似乎都在试图找到合适的方法,所以这是一个非常糟糕的方式:

List<int> doubles = new List<int>();
Dictionary<int, bool> seenBefore = new Dictionary<int, bool>();

foreach(int i in list)
{
    try
    {
        seenBefore.Add(i, true);
    }
    catch (ArgumentException)
    {
        doubles.Add(i);
    }
}

return doubles;

请不要那样做。

答案 3 :(得分:2)

这样的事情可能有用:

list.GroupBy (l => l).Where (l => l.Count () > 1).SelectMany (l => l).Distinct();

编辑:

上面的代码没有得到OP想要的结果。这是一个经过编辑的版本,它从以下Ani优雅解决方案中获取灵感::)

list.GroupBy(l => l).Select(g=>g.Skip(1)).SelectMany (l => l);

答案 4 :(得分:0)

这里你回答c#:)

int[] intarray = new int[] { 1, 1, 2, 3, 4, 4, 5, 7, 7, 7, 10 };

int previousnumber = -1;
List<int> doubleDigits = new List<int>();
for (int i = 0; i < intarray.Length; i++)
{
    if (previousnumber == -1) { previousnumber = intarray[i]; continue; }
    if (intarray[i] == previousnumber)
    {
        if (!doubleDigits.Contains(intarray[i]))
        {
            doubleDigits.Add(intarray[i]);
            //Console.WriteLine("Duplicate int found - " + intarray[i]);
            continue;
        }
    }
    else
    {
        previousnumber = intarray[i];
    }
}

答案 5 :(得分:0)

一个(可能)比使用Linq更好的例子,虽然可以说不那么优雅:

for (int i = 1; i < list.Count; i++)
    if (list[i] == list[i - 1])
        doubles.Add(list[i]);

答案 6 :(得分:0)

你可以这样做:

list.GroupBy(i => i).Where(g => g.Count() > 1).SelectMany(g => g.Skip(1))

这有点像@KJN的答案,除了我认为它在问题中表达了“双打”和“两个双打”条款更好一点:

  1. 将所有整数组合在一起
  2. 仅对那些出现多次(g.Count() > 1
  3. 的人感兴趣
  4. 选择“双打”的扁平列表,即第一个(g.Skip(1)
  5. 之后的列表

    PS:我们在这里假设,GroupBy不首先对列表进行排序,如果确实如此,那排序不会受到预先排序列表的负面影响......