我有一个数组数组 - 有关使用VSTO在Excel中选择的信息,其中每个元素表示开始和结束选择位置。
例如,
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
等。
答案 0 :(得分:3)
如果您想使用纯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();
希望有所帮助。
答案 1 :(得分:0)
首先,您需要一种比较整数数组的方法。要将它与框架中的类一起使用,可以通过创建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只丢弃重复值,因此它现在包含四个整数数组。