Как приравнять элементы двух массивов независимо от порядка записей - PullRequest
0 голосов
/ 15 июня 2009

Я пытаюсь подсчитать два массива, такие как myArray{a,b,c} и urArray{a,b,c,c}

Я хотел проверить, имеют ли оба элемента одинаковые элементы, например, в приведенном выше условии второй массив, urArray, имеет дополнительный 'c'.

И код должен иметь возможность приравнивать два набора массива , если они имеют одинаковые элементы или нет, а порядок элементов не имеет значения . Просто оба массива должны иметь одинаковые элементы, т. Е. Если у одного есть два «с», то у другого также должно быть два «с», в противном случае условие ложно.

Итак, что я сделал:

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

но не знаю, как показать, что, если массив имеет одинаковые элементы или нет ...

Как мне это сделать?

Ответы [ 9 ]

7 голосов
/ 15 июня 2009

Вот некоторый код C #, использующий linq, который должен выполнять эту работу, в основном это реализация формы последовательности сортировки / сравнения, которая является наиболее надежной. Этот код отсортирует обе последовательности и сравнит их на эквивалентность. Вы можете немного оптимизировать его, сначала проверив, что myArray и urArray имеют одинаковую длину, чтобы избежать ненужной сортировки.

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

Если вы по какой-то причине не можете (или не хотите) использовать linq, вот эквивалентная версия с использованием кода .NET 2.0:

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;
        }
4 голосов
/ 15 июня 2009

Вы можете отсортировать два массива, а затем последовательно сравнить элементы. Если в любое время сравниваемые два элемента различны, массивы содержат разные элементы.

3 голосов
/ 15 июня 2009

Это похоже на ту же проблему, что и у меня: Сравнение двух коллекций на равенство

2 голосов
/ 15 июня 2009

Предлагаю рассчитать разницу между гистограммами обеих последовательностей. Это будет даже работать, если последовательность не может быть отсортирована или нет эффективного способа определить длину последовательности.

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

Если длина последовательности может быть получена, проверка всех значений в словаре на ноль может быть заменена проверкой на равную длину последовательности.

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

Это решение - O(n), если затраты на создание словаря незначительны, а сортировка требует O(n*log(n)) времени.

1 голос
/ 19 июня 2009
return myArray.OrderBy(c => c).SequenceEqual(urArray.OrderBy(c => c));
1 голос
/ 15 июня 2009

Это однострочник с LINQ:

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

Кроме того, вы можете вызвать OrderBy для каждой последовательности, чтобы отсортировать их в том же порядке, а затем использовать Enumerable.SequenceEqual для их сравнения:

bool same = Enumerable.SequenceEqual (array1.OrderBy (n => n), array2.OrderBy (n => n));
0 голосов
/ 15 июня 2009

Сначала вы должны проверить, имеют ли массивы одинаковую длину.

Если это так, нам нужно отсортировать массивы.

Затем выполните цикл по обоим массивам и сравните каждый элемент.

    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
        ///

    }
0 голосов
/ 15 июня 2009

Если вы не можете использовать LINQ, это должно помочь:

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;
}
0 голосов
/ 15 июня 2009

Если ваши массивы содержат только уникальные элементы, я бы создал из них два HashSets, а затем вычел бы один из другого, чтобы увидеть, является ли результат пустым набором.

...