Как удалить дубликаты из int[][]

У меня есть массив массивов - информация о выборе в Excel с использованием VSTO, где каждый элемент означает начальную и конечную позицию выбора.

Например,

int[][] selection = {
new int[] { 1 }, // column A
new int[] { 6 }, // column F
new int[] { 6 }, // column F
new int[] { 8, 9 } // columns H:I
new int[] { 8, 9 } // columns H:I
new int[] { 12, 15 } // columns L:O
};

Не могли бы вы помочь мне найти способ, возможно, используя методы LINQ или Extension, удалить повторяющиеся элементы? Я имею в виду: F и F, H:I и H:I и т. д.


person abatishchev    schedule 31.03.2009    source источник
comment
Определите лучший способ: а) самый быстрый, б) самый простой для чтения код, в) использует наименьший объем памяти и т. д.   -  person Jason Kealey    schedule 31.03.2009
comment
Повторяющиеся строки? Что именно определяет, является ли строка одинаковой или нет — должна ли она быть точно такой же?   -  person Jon Skeet    schedule 31.03.2009
comment
Спасибо за исправление, я отредактировал свой пост   -  person abatishchev    schedule 31.03.2009


Ответы (2)


Если вы хотите использовать чистое решение метода LINQ/расширения, вам необходимо определить собственную реализацию IEqualityComparer для массивов/последовательностей. (Если я не упустил что-то очевидное, в BCL нет ранее существовавшего массива или компаратора последовательностей). Однако это не очень сложно — вот пример того, что должно хорошо справляться с этой задачей:

public class SequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return Enumerable.SequenceEqual(x, y);
    }

    // Probably not the best hash function for an ordered list, but it should do the job in most cases.
    public int GetHashCode(IEnumerable<T> obj)
    {
        int hash = 0;
        int i = 0;
        foreach (var element in obj)
            hash = unchecked((hash * 37 + hash) + (element.GetHashCode() << (i++ % 16)));
        return hash;
    }
}

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

var result = selection.Distinct(new SequenceEqualityComparer<int>()).ToArray();

Надеюсь, это поможет.

person Noldorin    schedule 31.03.2009

Сначала вам нужен способ сравнения целочисленных массивов. Чтобы использовать его с классами в фреймворке, вы делаете это, создавая EquailtyComparer. Если массивы всегда отсортированы, это довольно легко реализовать:

public class IntArrayComparer : IEqualityComparer<int[]> {

    public bool Equals(int[] x, int[] y) {
        if (x.Length != y.Length) return false;
        for (int i = 0; i < x.Length; i++) {
            if (x[i] != y[i]) return false;
        }
        return true;
    }

    public int GetHashCode(int[] obj) {
        int code = 0;
        foreach (int value in obj) code ^= value;
        return code;
    }

}

Теперь вы можете использовать целочисленный массив в качестве ключа в HashSet для получения уникальных массивов:

int[][] selection = {
    new int[] { 1 }, // column A
    new int[] { 6 }, // column F
    new int[] { 6 }, // column F
    new int[] { 8, 9 }, // columns H:I
    new int[] { 8, 9 }, // columns H:I
    new int[] { 12, 15 } // columns L:O
};

HashSet<int[]> arrays = new HashSet<int[]>(new IntArrayComparer());
foreach (int[] array in selection) {
    arrays.Add(array);
}

HashSet просто отбрасывает повторяющиеся значения, поэтому теперь он содержит четыре целочисленных массива.

person Guffa    schedule 31.03.2009