C# 删除重复项仅检查字符串数组的第一个元素

C# Remove Duplicates Only Checking on The First Element of The String Array

我有一个字符串数组列表。我想通过仅检查字符串数组的第一个元素来删除重复项和空字符串。我已经看到一些 SO 帖子使用 IEqualityComparer 来实现删除比较整个字符串数组的重复项,我认为这使它看起来更优雅并且可能更有效。但是我没能让它只在字符串数组的第一个元素上检查它以删除不需要的元素,因为 IEqualityComparer 让我感到困惑。我怎样才能更优雅地实现这一目标?我当前的非优雅和非高效工作代码:

void method(List<string[]> contactAndNumber)
{
    List<string[]> contactAndNumberSanitized = new List<string[]>();
    contactAndNumberSanitized.Clear();
    bool rem = false;
    List<int> remList = new List<int>();
    for (int i = 0; i < contactAndNumber.Count; i++)
    {
        contactAndNumberSanitized.Add(new string[] { contactAndNumber[i][0], contactAndNumber[i][1] });
        for (int j = 0; j < contactAndNumberSanitized.Count; j++)
            if (i != j)
                if (contactAndNumber[i][0] == contactAndNumberSanitized[j][0])
                {
                    rem = true;
                    break;
                }
        if (rem || string.IsNullOrEmpty(contactAndNumber[i][0]))
            remList.Add(i);
        rem = false;
    }
    for (int i = remList.Count - 1; i >= 0; i--)
        contactAndNumberSanitized.RemoveAt(remList[i]);
}

这是我试图实现的非工作代码,仅对字符串数组的第一项进行检查:

sealed class EqualityComparer: IEqualityComparer<string[]>
{
    public bool Equals(string[] x, string[] y)
    {
        if (ReferenceEquals(x[0], y[0]))
            return true;

        if (x == null || y == null)
            return false;

        return x[0].SequenceEqual(y[0]);
    }

    public int GetHashCode(string[] obj)
    {
        if (obj == null)
            return 0;

        int hash = 17;

        unchecked
        {
            foreach (string s in obj)
                hash = hash*23 + ((s == null) ? 0 : s.GetHashCode());
        }

        return hash;
    }
}

通过在某种方法下调用它:

var result = list.Distinct(new EqualityComparer());

您的代码可以大大简化:

var input = new List<string[]> { new[] { "a", "b" }, new[] { "a", "c" }, new[] { "c", "d" }};
var result = input.GroupBy(l => l.FirstOrDefault()).Select(g => g.First());

这将为您提供唯一的数组,使用每个数组的第一个元素来确定唯一性。

但是,由于您使用数组的第一个元素来确定唯一性,因此存在一个空集被视为等同于 { null } 的极端情况。根据您要如何处理空集,您需要修改代码以过滤输入,或更改 GroupBy

由于您正在使用 List,因此可以使用 RemoveAll 方法。

编辑:原始答案可能无效。修改如下。

编辑 2:实际上,如果您想删除所有重复项(不保留原件),请使用:

var duplicates = data.Where(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1).ToList();
data.RemoveAll(x => duplicates.Contains(x));

但是如果你想保留一组重复中的最后一个(例如一组三个 "A" 中的最后一个 "A"),那么你可以使用我的原始答案:

data.RemoveAll(x => x == null || string.IsNullOrEmpty(x[0]) || data.Where(y => y != null).Count(y => y[0] == x[0]) > 1);