首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用泛型将字典中的TValue转换为List<TValue>

如何使用泛型将字典中的TValue转换为List<TValue>
EN

Stack Overflow用户
提问于 2012-11-29 01:22:19
回答 4查看 302关注 0票数 0

首先,我是泛型的新手,所以我为任何错误提前道歉。

我希望能够以统一的方式比较不同类型的字典。我想比较两个可能有这种类型的字典(为了清楚起见,我想比较两个具有相同类型的不同字典):

代码语言:javascript
复制
Dictionary<string, Int32>
Dictionary<Int32, Int32>
Dictionary<string, string>
Dictionary<string, List<Int32>>
Dictionary<Int32, List<Int32>>
Dictionary<Int32, List<ComplexObject>>

使用泛型,我得到了以下代码:

代码语言:javascript
复制
 private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
    {
        var comp = EqualityComparer<TValue>.Default;
        if (left.Count != right.Count)
        {
            return false;
        }
        foreach (var pair in left)
        {
            TValue value;
            if ((typeof(TValue).Namespace == "System.Collections.Generic"))
            {
                TValue rightValue;
                right.TryGetValue(pair.Key, out rightValue);
                return ListEquals<TValue>(new List<TValue>(pair.Key), rightValue);
            }

            if (right.TryGetValue(pair.Key, out value) || (!comp.Equals(pair.Value, value)))
            {
                return false;
            }
        }
        return true;
    }

    private static bool ListEquals<TValue>(List<TValue> left, List<TValue> right)
    {
        if (left.Count != right.Count)
        {
            return false;
        }

        return left.All(right.Contains);
    }

我在调用ListEquals方法时遇到了问题,我不知道如何传入pair.key和rightValue参数。

感谢您的建议

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-11-29 01:58:09

我改变了你的代码,这是一个工作,但我不知道如何取代dynamic,这不是最好的选择сe,但解决了所有的造型问题。

代码语言:javascript
复制
        private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
        {
            var comp = EqualityComparer<TValue>.Default;
            if (left.Count != right.Count)
            {
                return false;
            }

            if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(List<>))
            {
                return left.All(pair => right.ContainsKey(pair.Key) && ListEquals((dynamic)pair.Value, (dynamic)right[pair.Key]));            
            }
            else
            {
                return left.All(pair => right.ContainsKey(pair.Key) && comp.Equals(pair.Value, right[pair.Key]));
            }
        }

        private static bool ListEquals<TValue>(List<TValue> left, List<TValue> right)
        {
            if (left.Count != right.Count)
            {
                return false;
            }

            return left.All(right.Contains);
        }
票数 0
EN

Stack Overflow用户

发布于 2012-11-29 01:35:56

如果TValue是rightValue类型,则TValue是List<SomeType>。但是使用ListEquals,而不是List<SomeValue>

票数 0
EN

Stack Overflow用户

发布于 2012-11-29 02:05:09

下面是我解决这个问题的方法:

代码语言:javascript
复制
private static bool DictionaryEquals<TKey, TValue>(Dictionary<TKey, TValue> left, Dictionary<TKey, TValue> right)
{
    var comp = EqualityComparer<TValue>.Default;
    if (left.Count != right.Count)
    {
        return false;
    }

    if (left.Keys.Intersect(right.Keys).Count() != left.Count)
        return false;
        //there is a key in the left dictionary that's not in the right dictionary
        //if there are any keys in the right dictionary not in the left then either 
        //there is one in the left not in the right as well, or the counts won't have 
        //been equal, so we know the two key sets are equal.

    var defaultValueComparer = EqualityComparer<TValue>.Default;

    Func<TValue, TValue, bool> valueComparer;

    if (typeof(TValue) is IEnumerable)
        valueComparer = (first, second) => ((IList)first).SequenceEqual((IList)second);
    else
        valueComparer = (first, second) => defaultValueComparer.Equals(first, second);

    foreach (var key in left.Keys)
    {
        if (!valueComparer(left[key], right[key]))
            return false;
    }

    return true;
}

public static bool SequenceEqual(this IList first, IList second)
{
    if (first.Count != second.Count)
        return false;

    IEnumerator iterator1 = first.GetEnumerator(),
                iterator2 = second.GetEnumerator();

    while (true)
    {
        bool next1 = iterator1.MoveNext();
        bool next2 = iterator2.MoveNext();
        // Sequences aren't of same length. We don't 
        // care which way round. 
        if (next1 != next2)
        {
            return false;
        }
        // Both sequences have finished - done 
        if (!next1)
        {
            return true;
        }
        if (!object.Equals(iterator1.Current, iterator2.Current))
        {
            return false;
        }
    }
}

有几个要点需要注意:

而不是让这两个集合是“集合比较”,我让它们是一个序列比较。如果他们真的应该有一个集合比较,那么对于他们来说,首先应该是列表之外的东西。无论如何,如果这是一个重要的更改,您可以将我的SequenceEqual方法的名称和实现修改为:

代码语言:javascript
复制
public static bool SetEquals(this IList first, IList second)
{
    if (first.Count != second.Count)
        return false;

    return first.OfType<object>().Intersect(second.OfType<object>())
        .Count() < first.Count;
}

与确定如何在foreach内部比较值相比,在外部比较更有意义;值的类型在循环中不会改变。确定一下比较函数是什么,然后一遍又一遍地调用它。委派对此很有帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13610867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档