繁体   English   中英

如何比较两个包含包含字典的对象的列表?

[英]How to compare two lists that contain objects that contain Dictionaries?

我有两个列表(列表“ A”和列表“ B”),其中包含“ KeyStore”类型的对象,如下所示:

public class KeyStore
{
    public Dictionary<string, string> PrimaryKeys { get; set; }

    public KeyStore(string pkName, string pkValue)
    {
        PrimaryKeys = new Dictionary<string, string> {{pkName, pkValue}};
    }

    public KeyStore()
    {
        PrimaryKeys = new Dictionary<string, string>();
    }
}

我需要查看列表“ A”中的每个记录,并查看列表“ B”中是否有匹配的记录。 如果存在,则此记录需要存储在仅包含匹配记录的新列表中。 如果记录的PrimaryKeys词典包含与列表“ B”中的记录相同的条目数和相同的键值组合,则认为匹配为true。 字典中条目的顺序对于测试是否相等并不重要。 如果列表“ A”中存在与列表“ B”不匹配的记录,则需要将其存储在仅包含在列表“ A”中找到的记录的新列表中。

以前,当我有字符串列表时,我使用“ Intersect”和“ Except”来创建匹配和不匹配记录的列表时,我做类似的事情。 我假设现在需要比较这些KeyStore对象,因此我需要提高复杂性。 谁能提供解决方案或建议我该如何解决此问题?

编辑1 ----------------

基于注释,我创建了一个实现IEqualityComparer的类,如下所示:

class KeyStoreComparer : IEqualityComparer<KeyStore>
{
    public bool Equals(KeyStore x, KeyStore y)
    {
        if (x != null && x.PrimaryKeys.Count == y.PrimaryKeys.Count)
        {
            return x.PrimaryKeys.Keys.All(k => y.PrimaryKeys.ContainsKey(k)) &&
                   x.PrimaryKeys.Keys.All(k => x.PrimaryKeys[k].Equals(y.PrimaryKeys[k]));
        }
        return false;
    }

    public int GetHashCode(KeyStore obj)
    {
        return ReferenceEquals(obj, null) ? 0 : obj.GetHashCode();
    }
}

我已经创建了一些虚拟数据,但是当运行“相交”命令时,从未调用以上代码。 有什么想法我要去哪里吗?

var ListA = new List<KeyStore>();
ListA.Add(new KeyStore("a", "b"));
ListA.Add(new KeyStore("c", "d"));

var ListB = new List<KeyStore>();
ListB.Add(new KeyStore("a", "b"));
ListB.Add(new KeyStore("x", "y"));

var g = ListA.Intersect(ListB, new KeyStoreComparer());

“ Equals”和“ GetHashCode”中的代码可能不正确,但是我只是想让它尽可能地运行,然后才能对其进行改进。

编辑2 ---------------------------------------

我已经对KeyStore类进行了各种更改,如本页中的示例“ fox”所示。 我仍然没有被调用的重写函数。 作为实验,我尝试了以下操作:

var result = ListA.Equals(ListB);

当我这样做时,KeyStor类中的重写功能不会运行。 但是,如果我这样做:

var result = ListA[0].Equals(ListB[0]);

重写的函数可以运行并给出预期的结果。 有谁知道我如何使它适用于列表中的所有项目,而不仅仅是单个记录?

编辑3 ---------------------------------------

我看到的问题是,该替代对于单个项目工作正常,例如:

var a = new KeyStore("a", "b");
var b = new KeyStore("a", "b");
var c = a.Equals(b);

当我在上面运行时,我在KeyStore“等于”功能上的断点被击中。 只要我尝试执行类似的操作但使用KeyStore列表,就不再会遇到断点。 使用列表时,我需要做些额外的事情吗?

public class KeyStore
{
    public Dictionary<string, string> PrimaryKeys { get; set; }

    public KeyStore(string pkName, string pkValue)
    {
        PrimaryKeys = new Dictionary<string, string> { { pkName, pkValue } };
    }

    public KeyStore()
    {
        PrimaryKeys = new Dictionary<string, string>();
    }

    public override bool Equals(object obj)
    {
        // If parameter is null return false.
        if (obj == null)
            return false;

        // If parameter cannot be cast to KeyStore return false.
        KeyStore targetKeyStore = obj as KeyStore;
        if (targetKeyStore == null)
            return false;

        return PrimaryKeys.OrderBy(pk => pk.Key).SequenceEqual(targetKeyStore.PrimaryKeys.OrderBy(pk => pk.Key));
    }

    public override int GetHashCode()
    {
        StringBuilder content = new StringBuilder();

        foreach (var item in PrimaryKeys.OrderBy(pk => pk.Key))
            content.AppendFormat("{0}-{1}", item.Key, item.Value);

        return content.ToString().GetHashCode();
    }
}

埃里克·利珀特(Eric Lippert)关于实现GetHashCode的指南中写道: “相等的项目具有相等的哈希值” 上面的GetHashCode()实现只是为了展示概念,可能不适合生产代码。

覆盖ToString方法将大大简化您的代码。 看看是否有帮助:

public class KeyStore
{
    public SortedDictionary<string, string> PrimaryKeys
    {
        get;
        set;
    }

    public KeyStore(string pkName, string pkValue)
    {
        PrimaryKeys = new SortedDictionary<string, string> { { pkName, pkValue } };
    }

    public KeyStore()
    {
        PrimaryKeys = new SortedDictionary<string, string>();
    }

    public override bool Equals(object obj)
    {
        if(obj == null || (KeyStore)obj == null)
            return false;
        KeyStore temp = (KeyStore)obj;

        return ToString() == temp.ToString();
    }

    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }
    public override string ToString()
    {
        return PrimaryKeys.Count.ToString() + " : \n" + string.Join("\n",(from kvp in PrimaryKeys
                                                                          let s = kvp.Key + " - " + kvp.Value
                                                                          select s));
    }
}

List<KeyStore> Lista = new List<KeyStore>
{
    new KeyStore("testa","testa1"),
    new KeyStore("testb","testb1"),
    new KeyStore("testc", "testc1")
};
List<KeyStore> Listb = new List<KeyStore>
{
    new KeyStore("testa","testa1"),
    new KeyStore("testd","testb1"),
    new KeyStore("testc", "testa1"),
    new KeyStore("teste", "teste1")
};
var Listc = Lista.Intersect(Listb).ToList();
var Listd = Lista.Except(Listb).ToList();

?Listc
Count = 1
    [0]: {1 : 
testa - testa1}

?Listd
Count = 2
    [0]: {1 : 
testb - testb1}
    [1]: {1 : 
testc - testc1}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM