我如何比较两个共享的属性上的两个标签



我需要比较两个相同类型的标签,但仅对于某些属性就有不同的值。我本质上需要一个更具体的除外。

我已经尝试使用Excestwith,但据我所知,这不允许您指定属性进行比较。

我们应该假装我不能将任何属性添加或删除任何属性。

   class Program
{
    private class Person
    {
        public string Name { get; set; }
        public string Id { get; set; }
    }
    static void Main(string[] args)
    {
        var people1 = new[]
        {
            new Person
            {
                Name = "Amos",
                Id = "123"
            },
            new Person
            {
                Name = "Brian",
                Id = "234"
            },
            new Person
            {
                Name = "Chris",
                Id = "345"
            },
            new Person
            {
                Name = "Dan",
                Id = "456"
            }
        };
        var people2 = new[]
        {
            new Person
            {
                Name = "Amos",
                Id = "098"
            },
            new Person
            {
                Name = "Dan",
                Id = "987"
            }
        };
        var hash1 = new HashSet<Person>(people1);
        var hash2 = new HashSet<Person>(people2);
        var hash3 = new HashSet<Person>(); // where hash3 is hash1 without the objects from hash2 solely based on matching names, not caring about Id matching
        foreach (var item in hash3) // should print out Brian, Chris
        {
            Console.WriteLine($"{item.Name}");
        }
    }
}

在您的Person类中,您应该定义自己的GetHashCode方法,以便它仅使用该人的名称而不是ID。

如果这样做,您还必须定义自己的 Equals方法:为什么覆盖等于equals方法时覆盖gethashcode很重要?

您可以将第二个数组中的名称放在linq滤波器中以创建最终的HashSet

var excludeName = new HashSet<string>(people2.Select(x => x.Name));
var hash3 = new HasSet<Person>(people1.Where(x => !exludeName.Contains(x.Name));

,如果要排除的值列表非常大,这将特别有用,因为它将整个过程以线性时间运行。

或这是您可以使用IEqualityComparer<T>设置HashSet s的方法。

public class PersonByNameComparer : IEqualityComparer<Peron>
{
    public bool Equals(Person p1, Persion p2)
    {
        return p1.Name == p2.Name;
    }
    public int GetHashCode(Person p)
    {
        return p.Name.GetHashCode();
    }
}

注意:这意味着即使Id不同,HashSet S也不能包含两个具有相同Name的项目。但这也意味着它不能包含具有与当前设置相同值的不同对象。

然后这样使用。

var comparer = new PersonByNameComparer();
var hash1 = new HashSet<Person>(people1, comparer);
var hash2 = new HashSet<Person>(people2, comparer);
// Note that ExceptWith will mutate the existing hash.  
hash1.ExceptWith(hash2); 
// Alternatively you can create the new hash like this
var hash3 = new HashSet<Persion>(hash1.Where(p => !hash2.Contains(p)));

您可以使用linq:

进行此操作
var hash3 = hash1.Where(x=>!hash2.Select(y=>y.Name).Contains(x.Name)).ToHashSet();

这仅创建了Hash2的名称的集合,然后从Hash1中获取所有名称不在该集合中的人。

最新更新