1

I do a function that find duplicate integers and store and utput number of them as they were arrays. I Create list called "Hit" for excluding operation for repetitive number. If I once have find all dupclicates for number I do not need do it again. But "Hit" List does not work. It gives me out of range error. For ex: I have array int[] in_number = {1, 2, 2, 4, 5, 6, 6}; Without "Hit" It would give me. I already do it. It works.

0
1 2
1 2
3
4
5 6 
5 6

Output

With "Hit" I try to do (it does not work)

0
1 2
3
4
5 6

But I wanna (best way)

1 2
5 6 

Here is code:

namespace arrow
{
    class Program
    {     
        static void Main(string[] args)
        {        
        int Min = 0;
        int Max = 10;
        int[] in_number = new int[100]; 
        Random randNum = new Random();
        for (int i = 0; i < in_number.Length; i++)
        {
            in_number[i] = randNum.Next(Min, Max);
        }                                           
        duplicate_number_List (in_number);                       
        }

        static void dupnumlist (int[] in_number) // Find duplicate numbers  
                {                        
                    List<List<int>> duplicate_pair = new List<List<int>>();
                    List<int> Hit = new List<int>();            
                    for (int i = 1; i < in_number.Length; i++)            
                    {                                                            
                        List<int> SubList = new List<int>();
                        foreach (int number in Hit)
                            {
                                if (number == in_number[i]) // Will match once 
                                {
                                    i++; // go to next iteration; passing unnecessary
                                }
                            }

                        for (int j = 0; j < in_number.Length; j++)
                        {
                            if (in_number[j]==in_number[i])
                            {                        
                                SubList.Add(j);
                                Hit.Add(in_number[i]);
                            }
                        }
                        duplicate_pair.Add(SubList);                
                    }  

                    foreach (var sublist in duplicate_pair)
                    {
                        foreach (var value in sublist)
                        {
                        Console.Write(value);
                        Console.Write(' ');
                        }
                        Console.WriteLine();
                    }
                    foreach (var value in Hit)
                    {
                        Console.Write(value);
                        Console.Write(' ');
                    }
                    Console.WriteLine();
                }              
    }
}

I don`t wanna use built-in functions

2 Answers2

1

It sounds like you're looking for something like this:

int[] in_number = {1, 2, 2, 4, 5, 6, 6};
var duplicates = 
    from a in in_number.Select((value, index) => new { value, index })
    group a by a.value into g
    where g.Count() > 1
    select g.First();

The first line selects each number in the integer list as well as its index as pairs. The second line groups pairs with the same value together. The third line filters out any groups with only one member. And finally, the last line returns the first pair in each group, which will contain the value as well as the lowest index.

You can then loop through the duplicates and write them out like this:

foreach (var dup in duplicates)
{
    Console.WriteLine("{0} {1}", dup.index, dup.value);
}

Update

If you can assume that the input array is already sorted, here is a solution using only a dictionary:

var previousValue = in_number[0];
var duplicates = new Dictionary<int, int>();
for(int i = 1; i < in_number.Length; i++) // Note: starting at 1 instead of 0
{
    if (previousValue == in_number[i] && !duplicates.ContainsKey(i))
    {
        duplicates.Add(previousValue, i - 1);
    }
    previousValue = in_number[i];
}

If the input array may not be sorted, then it's a bit more difficult, but you can still do it with a pair of Dictionaries:

var first = new Dictionary<int, int>();      // Stores the first instance of each value and its index
var duplicates = new Dictionary<int, int>(); // Stores any subsequent instances with the previous index
for(int i = 0; i < in_number.Length; i++)
{
    if (!first.ContainsKey(in_number[i]))
    {
        first.Add(in_number[i], i);
    } 
    else if (!duplicates.ContainsKey(in_number[i]))
    {
        duplicates.Add(in_number[i], first[in_number[i]]);
    }
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Nice thanks. But I do not wanna use in-bult functions or LINQ now. – user3103832 Dec 20 '13 at 03:18
  • @user3103832 Is there a reason for that? is this homework? Also, can we assume that the list is already sorted? – p.s.w.g Dec 20 '13 at 03:19
  • I do it for me. Of course this is not best alg but all I wanna is find some simple solution. – user3103832 Dec 20 '13 at 03:21
  • @user3103832 What about using built-in data structures, e.g. `Dictionary` or `HashSet`? Is that allowed? – p.s.w.g Dec 20 '13 at 03:23
  • Good idea. I already thinked about this. It is next my step after **List**. Another step is array of List. But I learning. I need to practice with Dictionary and HashSet. – user3103832 Dec 20 '13 at 03:25
0

Why not use a HashTable class? Store the values on Key and Value property on HashTable, then if it's equal to a previous entry, do not store it at all.

Refer to this, I promise this will be the easiest way.

Dustine Tolete
  • 461
  • 1
  • 7
  • 19
  • HashTables are basically untyped dictionaries. Using an untyped data structure when a perfectly good strongly typed one will work equally well is bad practice and is likely to end up causing more problems if overused. This is just practice for OP now, but we should not be handing out bad advice. – p.s.w.g Dec 20 '13 at 04:04