从配对列表中删除“重复”

时间:2015-11-05 17:18:29

标签: c# linq list lambda

标题可能会产生误导,举个例子:

我有一个班级:

class Pair
{
   Book Book1;
   Book Book2;
}

我有一份清单:

var list = new List<Pair>();

list.Add(new Pair() {
    Book1 = new Book() { Id = 123 },
    Book2 = new Book() { Id = 456 }
 });

list.Add(new Pair() {
    Book1 = new Book() { Id = 456 },
    Book2 = new Book() { Id = 123 }
 });

现在,尽管书籍被“翻转”,但我的系统应将这些书视为重复。

我需要一种从列表中删除一个这些'重复'的方法(任何一个 - 所以让我们说第一个让它变得简单)。

我尝试过什么

        var tempList = new List<Pair>();
        tempList.AddRange(pairs);

        foreach (var dup in pairs)
        {
            var toRemove = pairs.FirstOrDefault(o => o.Book1.Id == dup.Book2.Id
                                                       && o.Book2.Id == dup.Book1.Id);

            if (toRemove != null)
                tempList.Remove(toRemove);
        }

        return tempList;

这不返回任何项目(给出上面的例子),因为两个Pair对象都满足lambda中的条件,我只有一个删除一个。

注意:如果我立即从集合中删除元素(而不是从临时列表中删除),则不会发生这种情况 - 但是我无法在没有例外的情况下迭代它。

4 个答案:

答案 0 :(得分:4)

您可以设置IEqualityComparer<Pair>具体类并将其传递给.Distinct()方法:

class PairComparer : IEqualityComparer<Pair>
{
    public bool Equals(Pair x, Pair y)
    {
        return (x.Book1.Id == y.Book1.Id && x.Book2.Id == y.Book2.Id)
            || (x.Book1.Id == y.Book2.Id && x.Book2.Id == y.Book1.Id);
    }

    public int GetHashCode(Pair obj)
    {
        return obj.Book1.Id.GetHashCode() ^ obj.Book2.Id.GetHashCode();
    }
}

然后像这样使用它:

var distinctPairs = list.Distinct(new PairComparer());

答案 1 :(得分:2)

问题是你要删除这两个重复项。

试试这个:

byte b = (byte)((Version << 4) + IHL);

答案 2 :(得分:1)

我会使用以下

saveAsTextFile

这将特意删除&#34;乱序&#34;的副本。但是,如果重复对具有相同顺序的书籍,则此(和您的原始文件)将失败。

更好的解决方案(因为我们无论如何都要循环遍历)将使用HashSet

    foreach (var dup in pairs)
    {
        var toRemove = pairs.FirstOrDefault(o => o.Book1.Id == dup.Book2.Id
                                                   && o.Book2.Id == dup.Book1.Id
                                                   && o.Book1.Id > o.Book2.Id);

        if (toRemove != null)
            tempList.Remove(toRemove);
    }

答案 3 :(得分:0)

我设法找到了解决方案,但这是我不满意的解决方案。对于我正在尝试的工作来说,这似乎太冗长了。我现在正在进行额外的检查以查看是否已将副本添加到列表中:

 if(toRemove != null && tempList.Any(o => o.Book1.Id == toRemove.Book2.Id
                                       && o.Book2.Id == toRemove.Book1.Id))
                                           tempList.Remove(toRemove);

我非常愿意接受其他建议。