2

In my C# program, I have an int array containing a set of integers and occasionally duplicates of those integers. I want to create an array that only contains the numbers that exist as duplicates in the initial array, but in itself contains no duplicates. Based on my newbie understanding of C# I thought that the following code would do the trick:

int a = 9;
int b = 6;
int c = 3;
int index = 0;

int[] mltpls = new int[a + b + c];

while (a > 0)
{
    mltpls[index] = 2 * a;
    a -= 1;
    index += 1;
}

while(b > 0)
{
    mltpls[index] = 3 * b;
    b -= 1;
    index += 1;
}

while(c > 0)
{
    mltpls[index] = 5 * c;
    c -= 1;
    index += 1;
}

int[] mltpls_unique = mltpls.Distinct().ToArray();
int[] mltpls_dplcts = mltpls.Except(mltpls_unique).ToArray();

Console.WriteLine(mltpls_dplcts);

//EDIT

//By running the following code I can write out all numbers in "mltpls"
for (int i = 0; i < mltpls.Length; i++)
{
 Console.Write(mltpls[i] + ", ");
}

/*If I try to run equivalent code for the "mltpls_dplcts" array nothing
only a blank line is displayed.*/

When I run this goal my the final result of my console application is a blank row. My interpretation of this is that the array mltpls_dplcts is empty or that I'm incorrectly going about printing the array.

How do get only the duplicate values from an array?

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
K. Claesson
  • 603
  • 8
  • 22
  • 2
    Can you add the input array contents? It's rather difficult from the code to estimate what really is in that array. – PMF Dec 13 '17 at 07:34
  • 2
    This is better done use a List than an array. – jdweng Dec 13 '17 at 07:38
  • Possible duplicate of [Remove items from list that intersect on property using Linq](https://stackoverflow.com/questions/19175257/remove-items-from-list-that-intersect-on-property-using-linq) – pix Dec 13 '17 at 07:44
  • @PMF The array input of the array called "mltpls" is: 18, 16, 14, 12, 10, 8, 6, 4, 2, 18, 15, 12, 9, 6, 3, 15, 10, 5 – K. Claesson Dec 13 '17 at 07:46
  • "How do I delete all elements in an int array that exist in another int array in C#?" this question is misleading. If you remove all elements in `mltpls` that exist in `mltpls_unique` you remove them ALL! this is actually what you have done. But it seems that you want the duplicates singled out into a new array – Mong Zhu Dec 13 '17 at 08:05

5 Answers5

3

My interpretation of this is that the array mltpls_dplcts is empty or that I'm incorrectly going about printing the array.

Both interpretations are correct

Distinct will return every item that is at least once present in mltps. If you now apply Except you get nothing because all items that are in mltpls_unique are also present in mltps. The items in the array are compared by value, so for Except it does not matter whether a number occurs multiple times in the other array. If it is there once it will not return the number. So you get an empty array.

Furthermore you cannot simply shove an entire array into Console.WriteLine. Either use a loop or String.Join to print the content:

Console.WriteLine(String.Join(" ",mltpls_dplcts));

Solution: You can solve it using a good old loop approach ;)

int[] mltpls_unique = mltpls.Distinct().ToArray();
// The amount of duplicates is the difference between the original and the unique array
int[] mltpls_dplcts = new int[mltpls.Length-mltpls_unique.Length];


int dupCount = 0;
for (int i = 0; i < mltpls.Length; i++)
{
    for (int j = i+1; j < mltpls.Length; j++)
    {
        if (mltpls[i] == mltpls[j])
        {
            mltpls_dplcts[dupCount] = mltpls[i];
            dupCount++;
        }
    }
}

Output: 18 12 10 6 15

Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • @Mong_Zhu I understand that the above code solves the problem in question. However, I don't fully understand how it functions or what thoughts would need to go through my mind to come up with it. Specifically, I don't understand how the use of a for loop within a for loop helps us generate the sought after equality. – K. Claesson Dec 13 '17 at 08:39
  • 1
    @K.Claesson Think about how you would identify duplicates if they were written down on a piece of paper. You would remember the first number and scan the list to find it again. You would start to look at the position right to the remembered item (since you don't want to compare the item with itself) `IF` you find the number you write it down on a separate sheet of paper, otherwise you know that it is unique. Now you take the second element in the list, remember it and start again scanning. You problem is examplary for the use of loops. If you have more question don't hesitate to ask :) – Mong Zhu Dec 13 '17 at 08:49
  • @K.Claesson Imagine you put the left **index** finger on the first number that you try to remember and you use your right **index** finger to look for the duplicate. Now you fingers work as pointers or **indexers** which is basically also the use of the **index** variables (they are even called this way) in the 2 loops `i` and `j`. Each time you move the right finger you look back at the position where you left finger points to and compare the numbers, then you shift the right finger one position forward :) Is this somehow understandable? – Mong Zhu Dec 13 '17 at 08:52
  • @Mong_Zhu Yes, your analogy was superb for helping me interpret the code and understand the thought process behind it. Two questions: i) Is the reason we can say that the first, and equivalently second, for loop should execute while `i < mltpls.Length` because `mltpls.Length = x` whereas the last index mltpls is x - 1 due to indexes starting at 0? ii) Based on my interpretation of the code, if one number occurred _n_ times in mltpls, mltpls_dplcts would include that numner _n_ - 1 times. Is this correct? – K. Claesson Dec 13 '17 at 09:32
  • @K.Claesson i) " whereas the last index mltpls is x - 1 due to indexes starting at 0?" Yes. you could also run the first loop only until `mltpls.Length-1` because there is no need to compare the last element, since no other follow it. ii) that is correct since it counts only the positive comparisons. This is why the unique elements are not present and their count is `0` – Mong Zhu Dec 13 '17 at 09:40
1

You cannot print the array directly. You need to loop and print one by one:

foreach (var element in mltpls_dplcts)
{
    Console.WriteLine(element);
}
Sunil
  • 3,404
  • 10
  • 23
  • 31
1

You can get array of distinct duplicates like this:

var duplicates = mltpls.GroupBy(o => o)
    .Where(g => g.Count() > 1)
    .Select(g => g.First()).ToArray();

To get new array that contains only the elements from the original one that are not in the second array you can use:

var newArr = mltpls.Except(duplicates).ToArray();
eXavier
  • 4,821
  • 4
  • 35
  • 57
0

It is not proper way to find duplicates. You can determine the duplicates by using GroupBy and print them to console like this;

        var mltpls_dplcts = mltpls.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key).ToArray();
        foreach (var duplicate in mltpls_dplcts)
        {
            Console.WriteLine(duplicate);
        }

Also, If it isn't must to use Array for you, I suggest you to use List<int>.

lucky
  • 12,734
  • 4
  • 24
  • 46
0

Updated question from OP:

How do get only the duplicate values from an array?

var arr1 = new[] {1, 2, 4, 4, 5, 5, 5, 5, 6, 7, 1};
var duplicates = arr1.ToLookup(_ => _, _ => _).Where(_ => _.Count()>1).Select(_ => _.Key).ToArray();
// duplicates is now { 1, 4, 5 }

Original question from OP:

How do I delete all elements in an int array that exist in another int array in C#?

var arr1 = new[] {1, 2, 4, 5, 6, 7};
var arr2 = new[] {4, 5};

var hash = new HashSet<int>(arr1);
hash.ExceptWith(arr2);
var filteredArray = hash.ToArray();

// filteredArray is now { 1, 2, 6, 7 }
Dan Byström
  • 9,067
  • 5
  • 38
  • 68
  • unfortunately your examplke does not match that from the post. Your input need to look like this: `var arr1 = new[] { 1, 2, 4, 2, 5, 1, 4 };` and `var arr2 = new[] { 1, 2, 4, 5 };` with your approach you will get the same result as OP. – Mong Zhu Dec 13 '17 at 08:02
  • I see that OP has edited the question. :-( I answered "How do I delete all elements in an int array that exist in another int array in C#?", but now that question has been rephrased. – Dan Byström Dec 13 '17 at 11:08
  • I guess the question was misleading, since he described a different case than the question let assume. I edited and rephrased the question. He describes aim in his post as " I want to create an array that only contains the numbers that exist as duplicates in the initial array" – Mong Zhu Dec 13 '17 at 13:53