检查一个列表是否包含另一个列表中的任何元素

10

我只是想在一个列表中检查是否包含list2中的任何Name/Value,如果存在则返回true:

这将是我的结构:

public class TStockFilterAttributes
{
    public String Name { get; set; }
    public String Value { get; set; }
}

List<TStockFilterAttributes> List1 = new List<TStockFilterAttributes>();
List<TStockFilterAttributes> List2 = new List<TStockFilterAttributes>();

这应该返回true:
List1.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" });
List2.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" });

但是这会返回false,因为名称和值不匹配:

List1.Add(new TStockFilterAttributes { Name = "Foo", Value = "Bar" });
List2.Add(new TStockFilterAttributes { Name = "Foo", Value = "Foo" });

每个列表都可能包含许多不同的值,我只需要知道List1中的任何一个是否与List2中的任何一个匹配。
我尝试过使用:
return List1.Intersect(List2).Any();

但是在所有情况下似乎都返回false,我猜这是因为我在List中持有一个类而不是一个简单的int/string?


6
默认情况下,Intersect 操作基于引用进行比较。因为每次都会创建一个新的对象,所以你需要编写自己的 IEqualityComparer<TStockFilterAttributes> - Patryk Ćwiek
5个回答

8

为您的类覆盖 EqualsGetHashCode 实现:

public class TStockFilterAttributes
{
    public String Name { get; set; }
    public String Value { get; set; }

    public override bool Equals(object obj)
    {
        TStockFilterAttributes other = obj as TStockFilterAttributes;
        if (obj == null)
            return false;

        return Name == obj.Name && Value == obj.Value;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode() ^ Value.GetHashCode();
    }
}

或者为Intersect函数提供一个比较器。


我在发布问题后尝试了这个方法,它有效。当允许时,我会将其标记为答案,因为它与我的解决方案相同。谢谢。 - webnoob
@webnoob 没问题。问题出在默认的 EqualsGetHashCode 实现上,它们使用对象引用来比较不同的对象。Linq 使用这些方法进行比较。 - Sergey Berezovskiy

6
假设性能不重要:
List1.Any(l1 => List2.Any(l2 => l1.Key == l2.Key && l1.Value == l2.Value));

替代方法是覆盖Equals或将其设为结构体(可能不合适)。

3
var query = List1.Where(x => List2.Exists(y => y.Name == x.Name && y.Value == x.Value));

但性能可能很差。


1

问题在于您正在比较引用而不是对象。由于每次创建新对象,因此列表将永远不会保留相同的引用。

尝试:

var FooBar = new TStockFilterAttributes { Name = "Foo", Value = "Bar" };
var FooFoo = new TStockFilterAttributes { Name = "Foo", Value = "Foo" };
List1.Add(FooBar);
List2.Add(FooBar);
List2.Add(FooFoo);
return List1.Intersect(List2);

这就是我认为的问题所在,现在我已经实现了一个IEqualityComparer来解决这个问题。 - webnoob
当然。根据您的需求,您有两种方法可选。通常情况下,我们想要检查引用,但有时您只需要比较值。 - Pete

0

抱歉晚来一步,但是使用交集我们可以使用选择而避免使用等式。

list1.Select(Function(p) p.ItemID).Intersect(list2.Select(Function(p)p.ItemID)).Any()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接