Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Counting duplicate numbers in a list

Tags:

c#

list

I have an list:

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

Now I need to make a program which calculates the double numbers. A number is double when the number before it is the same. I hope you understand. So 1 is double, 4 is doubles and we got 2 double in 7,7,7.

like image 542
Rik Avatar asked Oct 01 '10 13:10

Rik


3 Answers

Here's a solution in LINQ:

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

This creates another sequence by skipping the first member of the list, and then finds elements from both sequences that have the same index and the same value. It will run in linear time, but only because a list offers O(1) access by index.

like image 148
Ani Avatar answered Nov 07 '22 10:11

Ani


Here's an approach which is relatively simple, only iterates once over the sequence, and works with any sequence (not just lists):

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;
        }
    }
}

Here's another one which is even simpler in that it's only a LINQ query, but it uses side-effects in the Where clause, which is nasty:

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;
});

A third alternative, which is somewhat cleaner but uses a SelectConsecutive method which is basically SelectPairs from this answer, but renamed to be slightly clearer :)

IEnumerable<int> sequence = ...;
IEnumerable<int> result = sequence.SelectConsecutive((x, y) => new { x, y })
                                  .Where(z => z.x == z.y);
like image 40
Jon Skeet Avatar answered Nov 07 '22 10:11

Jon Skeet


Everyone seems to be trying to find good ways of doing it, so here's a really bad way instead:

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;

Please don't do it like that.

like image 6
teedyay Avatar answered Nov 07 '22 12:11

teedyay