【问题标题】:Remove duplicate inner lists from a list of list<object> in c#从 c# 中的 list<object> 列表中删除重复的内部列表
【发布时间】:2014-03-05 20:28:35
【问题描述】:

对于这个模棱两可的标题,我深表歉意。我无法同时保持清晰和简洁。所以请随意更改它。

我有一个包含其他几个列表的大列表。而这些内部 List 包含 Column 对象。

List<List<Column>> listOfAllColumns;

假设我的内部列表包含不同的 Column 对象,如下所示:

list1 = {c1, c1, c2}
list2 = {c1, c2, c1}
list3 = {c2, c3}
list4 = {c1,c1, c2}

大列表包含以下列表: listOfAllColumns = {list1, list2, list3, list4}

现在我想要一个从 listOfAllColumns 列表中删除 重复列表 的方法。例如,它将查看上面的列表并删除 list4。

list1: c1,c1,c2
list2: c1,c2,c1
list3: c2,c3
list4: c1,c1,c2 (it is equal to list1 so it is a duplicate)

这是我的代码:

public class ColumnList
{
    public void RemoveDuplicateColumnTypes()
    {

        Column c1 = new Column() { SectionName = "C50", StirrupType = "Tie" };
        Column c2 = new Column() { SectionName = "C50", StirrupType = "Spiral" };
        Column c3 = new Column() { SectionName = "C40", StirrupType = "Tie" };


        List<Column> list1 = new List<Column>() { c1, c1, c2 };
        List<Column> list2 = new List<Column>() { c1, c2, c1 };
        List<Column> list3 = new List<Column>() { c2, c3 };
        List<Column> list4 = new List<Column>() { c1, c1, c2 };


        List<List<Column>> listOfAllColumns = new List<List<Column>>() { list1, list2, list3, list4 };

        var result = listOfAllColumns.Distinct();

    }
}

class Column
{
    public string SectionName;
    public string StirrupType;
    public int StirrupSize;
    public double StirrupSpacing;
}

顺便说一句,顺序很重要,例如 {c1, c2, c1} 与 {c2,c1,c1} 不同。

【问题讨论】:

  • 听起来你需要查看 Distinct 的重载,所以你可以传入你的比较器对象。
  • @RBarryYoung 现在我想要一个从 listOfAllColumns 列表中删除重复列表的方法。
  • @gunr2171 谢谢。它适用于对象列表吗?

标签: c# list


【解决方案1】:

您需要的是能够比较不同序列的IEqualityComparer。这并不难,因为它还可以比较其中的项目:

public class SequenceComparer<T> : IEqualityComparer<IEnumerable<T>>
{
    private IEqualityComparer<T> comparer;
    public SequenceComparer(IEqualityComparer<T> comparer = null)
    {
        this.comparer = comparer ?? EqualityComparer<T>.Default;
    }
    public bool Equals(IEnumerable<T> x, IEnumerable<T> y)
    {
        return x.SequenceEqual(y, comparer);
    }

    public int GetHashCode(IEnumerable<T> sequence)
    {
        unchecked
        {
            int hash = 19;
            foreach (var item in sequence)
                hash = hash * 79 + comparer.GetHashCode(item);
            return hash;
        }
    }
}

现在您需要做的就是创建一个IEqualityComparer&lt;Column&gt;,它能够比较两个列对象(通过您想要的任何有意义的方式,大概默认实现是不够的)。

然后你可以把这些传给Distinct:

var query = listOfAllColumns.Distinct(
    new SequenceComparer<Column>(new ColumnComparer()));

【讨论】:

  • 谢谢。 int hash = 19; 是什么意思?在这里做吗?
  • @Vahid 将哈希变量初始化为一个数字,特别是数字 19。虽然从技术上讲,任何数字都是有效的,但使用质数会降低冲突的几率,这很好,但肯定不是要求.
  • @Vahid 您需要根据您希望如何定义两列之间的相等性为您的Column 类定义一个比较器。假设类本身的 EqualsGetHashCode 方法尚未定义适当的行为,您可以在此处指定何时认为两个不同的列相等。如果他们已经这样做了,您可以省略该调用。
  • @Vahid:如果您不知道该怎么做,请查看下面我的(工作)实现。正如Servy所建议的那样,您可以在IEqualityComparer&lt;Column&gt;中使用它,而不是覆盖Equals+GetHashCode。
  • @Vahid:我已经在您的RemoveDuplicateColumnTypes 中对其进行了测试,它返回了前三个列表并删除了第四个。也许您还没有执行查询。请注意,Distinct 是使用延迟执行实现的。例如,您可以通过添加ToList() 来执行它。因此,要将它们从您的列表中删除,您需要重新分配它:listOfAllColumns = listOfAllColumns.Distinct(new ColumnListComparer()).ToList();
【解决方案2】:

我将实现一个自定义的IEqualityComparer&lt;IEnumerable&lt;Column&gt;&gt;,您可以将其用于Distinct

public class ColumnListComparer : IEqualityComparer<IEnumerable<Column>>
{
    public bool Equals(IEnumerable<Column> x, IEnumerable<Column> y)
    {
        if (x == null || y == null) return false;
        if (object.ReferenceEquals(x, y)) return true;
        return x.SequenceEqual(y);
    }

    public int GetHashCode(IEnumerable<Column> obj)
    {
        unchecked
        {
            int hash = 17;
            foreach(Column col in obj)
            {
                hash = hash * 23 + (col == null ? 0 : col.GetHashCode());
            }
            return hash;
        }
    }
}

现在可以了:

var result = listOfAllColumns.Distinct(new ColumnListComparer());

您还需要在您的班级Column 中覆盖Equals + GetHashCode

public class Column
{
    public string SectionName;
    public string StirrupType;
    public int StirrupSize;
    public double StirrupSpacing;

    public override bool Equals(object obj)
    {
        Column col2 = obj as Column;
        if(col2 == null) return false;
        return SectionName    == col2.SectionName
            && StirrupType    == col2.StirrupType 
            && StirrupSize    == col2.StirrupSize
            && StirrupSpacing == col2.StirrupSpacing;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + (SectionName ?? "").GetHashCode();
            hash = hash * 23 + (StirrupType ?? "").GetHashCode();
            hash = hash * 23 + StirrupSize.GetHashCode();
            hash = hash * 23 + StirrupSpacing.GetHashCode();
            return hash;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2016-11-06
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 1970-01-01
    相关资源
    最近更新 更多