1

How can I make a Function to compact an array with duplicate entries?

For example!

A function that will take a sorted array of integers and return the array compacted. That is, given an array containing: 1, 2, 6, 8, 8, 8, 9, 10, 10, when the function returns, the contents of the array should be: 1, 2, 6, 8, 9, 10.

This is NOT hw. I am trying to make a function that will do this.

5
  • Is this homework? If it is, please add the appropriate tag... Commented Jul 2, 2012 at 17:22
  • Can there be negative elements? (it wouldn't really matter, but it simplifies the code a little if I can make that assumption) Commented Jul 2, 2012 at 17:24
  • @Servy you don't have to do something "special" for the case where you don't have a last element yet if you can use a reserved value. Commented Jul 2, 2012 at 17:30
  • @harold You could use an int? for the previous and initialize it to null, and then you can be sure that the initial value will never be equal the current value. Commented Jul 2, 2012 at 17:32
  • @Servy that would be my second choice, after using a reserved value Commented Jul 2, 2012 at 17:34

3 Answers 3

7

How about:

array = array.Distinct().ToArray();

or, as a function:

private int[] RemoveDuplicates(int[] array)
{
    return array.Distinct().ToArray();
}

then call it with:

array = RemoveDuplicates(array);
Sign up to request clarification or add additional context in comments.

9 Comments

What about if you wanted to create a function to do it?
@MontyTheMack: why reinvent the wheel? unless this is homework, and if so, MARK IT SO!
you don't need to create a function to do this. A function already exists to do this. You [should] create functions when there is no existing function that does what you want.
@EricJ. Agreed, it is however a fantastic solution to this particular problem.
@EricJ. If the OP is using pre 3.5 then I would revise the answer after it was specified. At this point, it's a rather uncommon requirement so trying to code every answer in 1.0 or 2.0 unless asked is just not worthwhile in my eyes. As I just said, I agree LINQ is unused, and often forcibly applied to situations it just doesn't fit. This doesn't appear to be such a case. This is a situation where LINQ solves the problem quickly, simply, understandably, and without violating the design or purpose of LINQ in any way. It should only be avoided if the OP adds a constraint that prohibits it.
|
2

extension methods:

public static T[] RemoveDuplicates<T>(this T[] array)
{
    return array.Distinct().ToArray();
}

public static List<T> RemoveDuplicates<T>(this List<T> list)
{
    return list.Distinct().ToList();
}

using for array:

int[] array = new[] {1, 3, 4, 3};
array = array.RemoveDuplicates();

using for list:

List<int> list = new List<int> {1, 3, 4, 3};
list = list.RemoveDuplicates();

Comments

1

The most straightforward way is probably with Linq

array = array.Distinct().ToArray()

However, Linq is not always the fastest approach.

If you do not wish to use Linq, you can do something like this (untested, but close)

List<int> compacted = new List<int>();

// If array is not a local variable:
// Assign to a variable to avoid re-evaluating the property every loop iteration
// Otherwise use array.Length as the loop termination condition to enable array
// bounds check elimination.  Thanks @Harold for the insight
// http://blogs.msdn.com/b/clrcodegeneration/archive/2009/08/13/array-bounds-check-elimination-in-the-clr.aspx

int max = array.Length; 

int last = 0;
for (int i=0; i < max; i++)
{
    if (i == 0)
    {
        compacted.Add(array[i]);
        last = array[i];
    }
    else
    {
        if (array[i] != last) compacted.Add(array[i]);
        last = array[i];
    }
}


array = compacted.ToArray();

6 Comments

Not caching array.Length here would actually enable array bounds check elimination.
@Harold: I don't follow you. My understanding is that the compiler is forced to re-evaluate Array.Length for every iteration because it cannot assume that the value does not change during the iteration of the loop body (either as a side effect of the body, or through a different thread). Could you clarify your point?
That applies when the array isn't a local variable, otherwise the code for for(int i = 0; i < Array.Length; i++) etc; is a special case in which the JIT compiler doesn't bounds-check array accesses indexed by i.
@Harold: Thanks for pointing that out. I didn't know about that optimization. I updated my answer accordingly.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.