Сравнение массивов с использованием LINQ в C # - PullRequest
21 голосов
/ 26 мая 2010

У меня есть два массива, как

string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };

Мне нужно сравнить два массива с помощью LINQ.

Сравнение должно проводиться, только если оба массива имеют одинаковый размер. Данные могут быть в любом порядке и по-прежнему возвращать true, если все значения a [] и все значения b [] совпадают.

Ответы [ 6 ]

28 голосов
/ 26 мая 2010
string[] a = { "a", "b" };
string[] b = { "a", "b" };

return (a.Length == b.Length && a.Intersect(b).Count() == a.Length);

После некоторого тестирования производительности:

  • Более 10000 маленьких строк - 5 мс
  • Более 100 000 маленьких строк - 99 мс
  • Более 1 000 000 маленьких строк - ср. 601ms
  • Более 100 000 ~ 500 строк символов - 190 мс
25 голосов
/ 26 мая 2010

Не уверен насчет производительности, но, похоже, это работает.

string[] a = { "a", "b", "c" };
string[] b = { "a", "b", "c" };

bool result = a.SequenceEqual(b);
Assert.AreEqual(true, result);

Тем не менее, он не зависит от порядка, поэтому он не соответствует требованию OP.

string[] a = { "a", "b", "c" };
string[] b = { "a", "c", "b" };

bool result = a.SequenceEqual(b);
Assert.AreEqual(false, result);
5 голосов
/ 26 мая 2010

Я думаю, что это всегда будет операция O (n log n), поэтому я просто отсортировал бы оба массива и сравнил их, например. используя SequenceEqual.

4 голосов
/ 26 мая 2010

если порядок не имеет значения или могут быть дубликаты, то возможно:

public static class IEnumerableExtensions
{
    public static bool HasSameContentsAs<T>(this ICollection<T> source,
                                            ICollection<T> other)
    {
        if (source.Count != other.Count)
        {
            return false;
        }
        var s = source
            .GroupBy(x => x)
            .ToDictionary(x => x.Key, x => x.Count());
        var o = other
            .GroupBy(x => x)
            .ToDictionary(x => x.Key, x => x.Count());
        int count;
        return s.Count == o.Count &&
               s.All(x => o.TryGetValue(x.Key, out count) &&
                          count == x.Value);
    }
}

использование:

string[] a = { "a", "b", "c" };
string[] b = { "c", "a", "b" };

bool containSame = a.HasSameContentsAs(b);

некоторые варианты использования:

  • разной длины (ожидается ложь)

    string[] a = { "a", "b", "c" };
    string[] b = { "b", "c" };
    
  • другой порядок (ожидаемо верно)

    string[] a = { "a", "b", "c" };
    string[] b = { "b", "c", "a" };
    

также работает, если входные данные могут содержать повторяющиеся элементы, хотя из вопроса, является ли эта характеристика желательной или нет, неясно, рассмотрим:

  • Дублированные элементы имеют одинаковое количество (ожидаемо)

    string[] a = { "a", "b", "b", "c" };
    string[] b = { "a", "b", "c", "b" };
    
  • дубликаты предметов с разным количеством (ожидаемо ложно)

    string[] a = { "a", "b", "b", "b", "c" };
    string[] b = { "a", "b", "c", "b", "c" };
    
3 голосов
/ 10 января 2012
IDictionary<int, object> a = new Dictionary<int, object>();
IDictionary<int, object> b = new Dictionary<int, object>();
a.Add(1, "1");
a.Add(2, 2);
a.Add(3, "3");

b.Add(3, "3");
b.Add(1, "1");
b.Add(2, 2);

Console.WriteLine(a.All(i => b.Contains(i)) && b.All(i => a.Contains(i)));
2 голосов
/ 10 января 2017

Это работает правильно с дубликатами и проверяет каждый элемент

a.Length == b.Length && !a.Where((t, i) => t != b[i]).Any()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...