如何从int [] []中删除重复项

时间:2020-12-08 12:58:55

I have an array of arrays - information about selection in Excel using VSTO, where each element means start and end selection position.

我有一个数组数组 - 有关使用VSTO在Excel中选择的信息,其中每个元素表示开始和结束选择位置。

For example,

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

Could you please help me to find a way, maybe using LINQ or Extension methods, to remove duplicated elements? I mean: F and F, H:I and H:I, etc.

你能帮我找到一种方法,可能使用LINQ或Extension方法来删除重复的元素吗?我的意思是:F和F,H:我和H:我等

2 个解决方案

#1


If you want to use a pure LINQ/extension method solution, then you'll need to define your own implementation of IEqualityComparer for arrays/sequences. (Unless I'm missing something obvious, there's no pre-existing array or sequence comparer in the BCL). This isn't terribly hard however - here's an example of one that should do the job pretty well:

如果您想使用纯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;
    }
}

The advantage of this is that you can then simply call the following to remove any duplicate arrays.

这样做的好处是您可以简单地调用以下内容来删除任何重复的数组。

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

Hope that helps.

希望有所帮助。

#2


First you need a way to compare the integer arrays. To use it with the classes in the framework, you do that by making an EquailtyComparer. If the arrays are always sorted, that is rather easy to implement:

首先,您需要一种比较整数数组的方法。要将它与框架中的类一起使用,可以通过创建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;
    }

}

Now you can use an integer array as key in a HashSet to get the unique arrays:

现在,您可以使用整数数组作为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);
}

The HashSet just throws away duplicate values, so it now contains four integer arrays.

HashSet只丢弃重复值,因此它现在包含四个整数数组。

#1


If you want to use a pure LINQ/extension method solution, then you'll need to define your own implementation of IEqualityComparer for arrays/sequences. (Unless I'm missing something obvious, there's no pre-existing array or sequence comparer in the BCL). This isn't terribly hard however - here's an example of one that should do the job pretty well:

如果您想使用纯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;
    }
}

The advantage of this is that you can then simply call the following to remove any duplicate arrays.

这样做的好处是您可以简单地调用以下内容来删除任何重复的数组。

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

Hope that helps.

希望有所帮助。

#2


First you need a way to compare the integer arrays. To use it with the classes in the framework, you do that by making an EquailtyComparer. If the arrays are always sorted, that is rather easy to implement:

首先,您需要一种比较整数数组的方法。要将它与框架中的类一起使用,可以通过创建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;
    }

}

Now you can use an integer array as key in a HashSet to get the unique arrays:

现在,您可以使用整数数组作为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);
}

The HashSet just throws away duplicate values, so it now contains four integer arrays.

HashSet只丢弃重复值,因此它现在包含四个整数数组。