1

I am trying to tally two arrays like myArray{a,b,c} and urArray{a,b,c,c}

I wanted to check if both the elements have same elements ,for example in above condition the second array that is urArray has an extra 'c' .

And the code should be able to equate two sets of array if they have the same elements or not and the order of the elements doesn't matter. Just that both arrays should have same elements i.e if one has two 'c' the other should also have two 'c' otherwise the condition is false.

So what I did was:

char[] myArray = new char[] {'a','b','c','c'};
char[] urArray = new char[] { 'a', 'b', 'c' ,'a'};
List<char> tmp2 = new List<char>(urArray);

for (int i = 0; i < myArray.Length; ++i)
{
    for (int j = 0; j < urArray.Length; ++j)
    {
        if (myArray[i] == urArray[j])
        {

            Console.WriteLine(urArray[j] + "--> " + "urArray"+"  myArray"+"--> "+myArray[i]);
            tmp2.Remove(urArray[j]);

            urArray = tmp2.ToArray();

        }
        else if (myArray[i] != urArray[j])
        {
            Console.WriteLine(myArray[i] + "--> " + "myArray" + "  urArray" + "--> " + urArray[j]);
        }
    }
}

but have no idea how to show that if the array have same elements or not ...

How can I accomplish this?

nawfal
  • 70,104
  • 56
  • 326
  • 368
jarus
  • 1,853
  • 11
  • 44
  • 76
  • 2
    Really bad idea to be modifying urArray while you're iterating through it. It's an error waiting to happen. – Adam V Jun 15 '09 at 14:44
  • possible duplicate of [Comparing two collections for equality irrespective of the order of items in them](http://stackoverflow.com/questions/50098/comparing-two-collections-for-equality-irrespective-of-the-order-of-items-in-the) – nawfal Nov 08 '13 at 20:16

9 Answers9

9

Here's some C# code using linq that should do the job, it's basically an implementation of the sort/compare sequence form - which is the most reliable. This code will sort both sequences and compare the for equivalence. You could optimize it slightly, by first checking that myArray and urArray are of the same length, to avoid unnecessary sorting.

char[] myArray = new char[] {'a','b','c','c'};
char[] urArray = new char[] { 'a', 'b', 'c' ,'a'};

var areEqual = myArray.OrderBy( x => x )
                      .SequenceEqual( urArray.OrderBy( x => x ) );

If you can't (or don't want to) use linq for some reason, here is an equivalent version using .NET 2.0 code:

public static bool AreEquivalentArray( char[] a, char[] b )
        {
            if (a.Length != b.Length)
                return false;

            Array.Sort(a);
            Array.Sort(b);
            for (int i = 0; i < a.Length; i++)
            {
                if( !a[i].Equals( b[i] ) )
                    return false;
            }
            return true;
        }
LBushkin
  • 129,300
  • 32
  • 216
  • 265
  • 1
    The question is tagged as "visualstudio2005" which suggests that a non-LINQ solution is required. – LukeH Jun 15 '09 at 15:15
  • The solution must be able to handle the arrays being of different lengths as there could be duplicates – James Jun 15 '09 at 16:58
  • This is not how I understood it, the original question states: "equate two sets of array if they have the same elements or not and the order of the elements doesn't matter just that both array should have same elements i.e if one has two 'c' the other should also have two 'c' otherwise the condition is false" – LBushkin Jun 15 '09 at 18:03
  • My original solution did just that and I was told it was wrong so I assumed jarus wanted some form of handling to deal with duplicates....I may be wrong lol – James Jun 15 '09 at 18:26
4

You could sort the two arrays and then sequentially compare elements. If at any time the two elements being compared are different the arrays contain different elements.

David Johnstone
  • 24,300
  • 14
  • 68
  • 71
3

This seems like the same issue I had: Comparing Two Collections for Equality

Community
  • 1
  • 1
mbillard
  • 38,386
  • 18
  • 74
  • 98
  • Why do you perform this complex key look-up in your solution? Why not just ContainsKey()? You have comments in your code saying that the dictionary uses reference equality, but that is not true. If TKey is a value type, there is no reference equality at all. Could you elaborate on this? Maybe I am missing an important point. – Daniel Brückner Jun 15 '09 at 18:20
  • If a collection contains two of the same, but the other collection contains only once, if I don't do key look-ups with counters, I won't know that the collections are different. I also mention that the code as it is compares for equality. If the objects are reference-type (objects), then their reference will be compared. So if I have two instances of the same object, they won't be equal. – mbillard Jun 15 '09 at 19:23
2

I suggest to calculate the difference between the histograms of both sequences. This will even work if the sequence cannot be sorted or there is no efficient way to determine the length of a sequence.

public static Boolean CompareCollections<T>(IEnumerable<T> a, IEnumerable<T> b)
{
    Dictionary<T, Int32> histogram = new Dictionary<T, Int32>();

    foreach (T item in a)
    {
        Int32 count;
        if (histogram.TryGetValue(item, out count))
        {
            histogram[item]++;
        }
        else
        {
            histogram[item] = 1;
        }
    }

    foreach (T item in b)
    {
        Int32 count;
        if (histogram.TryGetValue(item, out count))
        {
            if (count <= 0)
            {
                return false;
            }

            histogram[item]--;
        }
        else
        {
            return false;
        }
    }

    foreach (Int32 value in histogram.Values)
    {
        if (value != 0)
        {
            return false;
        }
    }

    return true;
}

If the length of the sequence can be obtained, checking all values in the dictionary to be zero can be replaced by an check for equal sequence lengths.

public static Boolean CompareCollections<T>(ICollection<T> a, ICollection<T> b)
{
    if (a.Count != b.Count)
    {
        return false;
    }

    Dictionary<T, Int32> histogram = new Dictionary<T, Int32>();

    foreach (T item in a)
    {
        Int32 count;
        if (histogram.TryGetValue(item, out count))
        {
            histogram[item]++;
        }
        else
        {
            histogram[item] = 1;
        }
    }

    foreach (T item in b)
    {
        Int32 count;
        if (histogram.TryGetValue(item, out count))
        {
            if (count <= 0)
            {
                return false;
            }

            histogram[item]--;
        }
        else
        {
            return false;
        }
    }

    return true;
}

This solution is O(n) if the costs of building the dictionary are negligible while sorting requires O(n*log(n)) time.

Daniel Brückner
  • 59,031
  • 16
  • 99
  • 143
1
return myArray.OrderBy(c => c).SequenceEqual(urArray.OrderBy(c => c));
m1k4
  • 829
  • 2
  • 12
  • 26
1

This is a one-liner with LINQ:

bool same = !array1.Except (array2).Any() && !array2.Except (array1).Any();

Alternatively, you could call OrderBy on each sequence to sort them in the same order and then use Enumerable.SequenceEqual to compare them:

bool same = Enumerable.SequenceEqual (array1.OrderBy (n => n), array2.OrderBy (n => n));
Joe Albahari
  • 30,118
  • 7
  • 80
  • 91
  • The first version is incorrect as it will incorrectly report arrays of different sizes as being equivalent, as well as not correctly dealing with duplicates. The second version will be correct. Sort then compare sequences. – LBushkin Jun 15 '09 at 14:53
  • Yes - you're quite correct. Given the question, Except() won't do the job. – Joe Albahari Jun 15 '09 at 14:55
  • The question is tagged as "visualstudio2005" which suggests that a non-LINQ solution is required. – LukeH Jun 15 '09 at 15:06
0

If your arrays only contain unique elements, I would create two HashSets from them and then subtract one from the other to see if the result is the empty set.

Andriy Volkov
  • 18,653
  • 9
  • 68
  • 83
  • 1
    The question is tagged as "visualstudio2005". If that's the case then HashSet wouldn't be available. – LukeH Jun 15 '09 at 15:08
0

If you're unable to use LINQ then this should do the trick:

char[] myArray = new char[] { 'a', 'b', 'c', 'c' };
char[] urArray = new char[] { 'a', 'b', 'c' ,'a' };

Console.WriteLine(AreEqual(myArray, urArray));    // False

// ...

public bool AreEqual<T>(IEnumerable<T> first, IEnumerable<T> second)
{
    Dictionary<T, int> map = new Dictionary<T, int>();

    foreach (T item in first)
    {
        if (map.ContainsKey(item))
            map[item]++;
        else
            map[item] = 1;
    }

    foreach (T item in second)
    {
        if (map.ContainsKey(item))
            map[item]--;
        else
            return false;
    }

    foreach (int i in map.Values)
    {
        if (i != 0)
            return false;
    }
    return true;
}
LukeH
  • 263,068
  • 57
  • 365
  • 409
0

First you one should check if the arrays are the same length.

If they are then we need to sort the arrays.

Then loop through both arrays and compare each element.

    char[] myArray = new char[] { 'a', 'b', 'c', 'c' };
    char[] urArray = new char[] { 'a', 'b', 'c', 'a' };


    if (myArray.Length.Equals(urArray.Length))
    {
        ///
        /// sort arrays
        ///

        System.Array.Sort(myArray);
        System.Array.Sort(urArray);

        for (int i = 0; i < myArray.Length; i++)
        {
            if (myArray[i] != urArray[i])
            {
                ///
                /// Arrays do not have same elements.
                ///
                break;

            }

        }
        ///
        /// if reach this code path the two arrays are equal.
        ///


    } else
    {
        ///
        /// Arrays not equal lenght
        ///

    }
TonyAbell
  • 1,310
  • 4
  • 19
  • 28