比较两个自定义对象(使用 IEqualityComparer)

发布于 2024-12-22 00:14:41 字数 2635 浏览 2 评论 0原文

首先,我会说我想要比较以下内容:我的自定义对象(项目)有一个字符串taxids列表。我想查看一个列表中的所有字符串是否都出现在另一个字符串列表中(也将是另一个对象(项目)的另一个taxids)。

所以,这就是类:

public class Item
{
    public long taxid { get; set; }
    public long contentid { get; set; }
    public string taxname { get; set; }
    public IEnumerable<string> taxids { get; set; }
}

然后这些是虚拟自定义对象:

    List<string> numbers = new List<string> { "5", "1" };
    List<string> numbers2 = new List<string> { "1", "2", "5","3","564" };

    Item pr = new Item();
    pr.contentid = 2517;
    pr.taxid = 2246;
    pr.taxids = numbers.AsEnumerable();
    pr.taxname = "nameItem1";
    List<Item> te = new List<Item>();
    te.Add(pr);
    IQueryable<Item> er = te.AsQueryable();

    Item pr2 = new Item();
    pr2.contentid = 0;
    pr2.taxid = 0;
    pr2.taxids = numbers2.AsEnumerable();
    pr2.taxname = "nameItem2";
    List<Item> te2 = new List<Item>();
    te2.Add(pr2);
    IQueryable<Item> er2 = te2.AsQueryable();

    IQueryable<Item> both = er.Intersect(er2, new ItemComparer());

这里我使用自定义比较器ItemComparer。这是其代码:

public class ItemComparer : IEqualityComparer<Item>
{
    // items are equal if their names and item numbers are equal.
    public bool Equals(Item x, Item y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        //Check whether the items' properties are equal.
        return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.
    public int GetHashCode(Item item)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(item, null)) return 0;

        //Get hash code for the Name field if it is not null.
        int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode();

        //Calculate the hash code for the item.
        return item.taxids.GetHashCode();

        //return "a".GetHashCode();
    }
}

问题是变量both在taxids字段中没有任何内容,通常我应该有一个列表。 “5”“1”

我知道 。比较时 hashCode 必须相同,但 taxids 永远不会相同。

有人可以进一步帮助我解决这个问题吗

"a".GetHashCode() => 之类的所有内容始终返回相同的哈希码,这是否可行?

如果我对

Firstly, I will say what I want to compare the following: My Custom Object (Item) has a List of strings taxids. I want to look if all the strings in one List occur in another list of strings (will be also another taxids of another Object (Item).

So, this is the class:

public class Item
{
    public long taxid { get; set; }
    public long contentid { get; set; }
    public string taxname { get; set; }
    public IEnumerable<string> taxids { get; set; }
}

Then these are the dummy custom objects:

    List<string> numbers = new List<string> { "5", "1" };
    List<string> numbers2 = new List<string> { "1", "2", "5","3","564" };

    Item pr = new Item();
    pr.contentid = 2517;
    pr.taxid = 2246;
    pr.taxids = numbers.AsEnumerable();
    pr.taxname = "nameItem1";
    List<Item> te = new List<Item>();
    te.Add(pr);
    IQueryable<Item> er = te.AsQueryable();

    Item pr2 = new Item();
    pr2.contentid = 0;
    pr2.taxid = 0;
    pr2.taxids = numbers2.AsEnumerable();
    pr2.taxname = "nameItem2";
    List<Item> te2 = new List<Item>();
    te2.Add(pr2);
    IQueryable<Item> er2 = te2.AsQueryable();

    IQueryable<Item> both = er.Intersect(er2, new ItemComparer());

Here I use a custom comparer ItemComparer. Here is the code for this:

public class ItemComparer : IEqualityComparer<Item>
{
    // items are equal if their names and item numbers are equal.
    public bool Equals(Item x, Item y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        //Check whether the items' properties are equal.
        return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.
    public int GetHashCode(Item item)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(item, null)) return 0;

        //Get hash code for the Name field if it is not null.
        int hashItemName = item.taxids == null ? 0 : item.taxids.GetHashCode();

        //Calculate the hash code for the item.
        return item.taxids.GetHashCode();

        //return "a".GetHashCode();
    }
}

The problem is that variable both has nothing in the taxids field, normally I should have a list of "5" "1".

I know that the hashCode must be the same when comparing. but taxids will be never the same. Because we look for strings in another list of strings.

Anybody can further help me with this problem?

(Also a small question: If I return always the same hashcode for everything like "a".GetHashCode() => should this work or not?

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沧桑㈠ 2024-12-29 00:14:41

我认为你的问题是你没有双向平等。 pr 和 pr 2 不相等,具体取决于对象的哪一侧。

我不确定您的比较器中是否能保证哪个对象是 x,哪个对象是 y。如果比较器中的 pr2 最终为 x 怎么办?

关于哈希码,您正在执行 taxids.GetHashCode() - 这只是一个列表,而不是名称,不会告诉您任何有关相等性的信息。

I think your problem is that you do not have bidirectional equality. depending on which side your object is, pr and pr 2 are not equal.

I am uncertain whether there is a guarantee which object is x and which is y in your comparer. What if pr2 ends up to be x in your comparer?

with regard to the hash code, you are doing taxids.GetHashCode() - that is just a list and not a name and won't tell you anything about equality.

瑕疵 2024-12-29 00:14:41
return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);

您的相等比较当前不考虑集合中元素的不同顺序。作为一个粗略的解决方法,您可以在比较之前对它们进行排序,或者更好地将项目添加到哈希集中:

return x.taxids.Intersect(y.taxids)
               .OrderBy(x => x)
               .SequenceEqual(x.taxids.OrderBy(x => x));

此外,您还必须提供 GetHashCode() 的适当实现,默认实现不依赖于实际项目在列表中,因此对于集合中具有相同元素的两个不同 Item 实例,不会产生相同的哈希码。可以在 这篇其他 SO 帖子<中找到更适合您的情况的实现/a>.

return x.taxids.Intersect(y.taxids).SequenceEqual(x.taxids);

Your equality comparison does currently not take into account the different order of elements in the collections. As a crude workaround you could order them before comparing, or better add the items to a hashset:

return x.taxids.Intersect(y.taxids)
               .OrderBy(x => x)
               .SequenceEqual(x.taxids.OrderBy(x => x));

Also you have to provide an appropriate implementation of GetHashCode(), the default implementation is not dependent on the actual items in the list, so wouldn't result in the same hashcode for two different Item instances that have the same elements in the collection. A more appropriate implementation for your case can be found in this other SO post.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文