Как удалить дубликаты из int[][]
-
22-08-2019 - |
Вопрос
У меня есть массив массивов - информация о выборе в 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 или методы расширения, удалить дублирующиеся элементы?Я имею в виду: F
и F
, H:I
и H:I
, и т.д.
Решение
Если вы хотите использовать чистое решение LINQ / extension method, то вам нужно будет определить свою собственную реализацию 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();
Надеюсь, это поможет.
Другие советы
Сначала вам нужен способ сравнения целочисленных массивов.Чтобы использовать его с классами фреймворка, вы делаете это, создавая 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 просто отбрасывает повторяющиеся значения, поэтому теперь он содержит четыре массива целых чисел.