判断字典对中的所有值是否相等

本文关键字:是否 字典 判断 | 更新日期: 2023-09-27 18:15:22

我有一个由点和力组成的字典,像这样:

public Dictionary<Point, Force> PointForceSet;

我想写一个函数,告诉我所有的力是否相同。到目前为止,我有这个:

public bool IsUniform()
{
    foreach (var item in PointForceSet)
    {
       //?
    }
}

确定键值对中的所有值是否相等的最简单方法是什么?

判断字典对中的所有值是否相等

如果您的值有有意义的默认比较器(如数字),这就足够了:

public bool IsUniform()
{    
    return PointForceSet.Values.Distinct().Count() == 1;
}

但是,如果有类(如您的Force),请记住覆盖GetHashCodeEquals,以允许真正区分Force对象实例,例如:

class Force
{
    public int X;
    public int Y;
    public override bool Equals(object obj)
    {
        Force other = obj as Force;
        return other != null && X == other.X && Y == other.Y;
    }
    public override int GetHashCode()
    {
        return 17 * X + Y;
    }
}

您可以使用LINQ提取第一个值,并检查以确保其他值都匹配:

public bool IsUniform()
{
    var values = PointForceSet.Values;
    if (values.Count == 0)
        return false; // Normally would be true - handling your req. based on comments
    var first = values.First();
    return values.Skip(1).All(v => v.Equals(first));
}

你应该调用

PointForceSet.Distinct() 

传入

IEqualityComparer<KeyValuePair<Point, Force>> 

执行。

如果字典中有条目,而. distinct()只返回一个条目,根据比较器代码,所有条目都是"相同的"。

为了允许在发现非相等对时立即短路,理想的解决方案是简单地遍历序列,将每一项与第一项进行比较。

public static bool AreSame<T>(this IEnumerable<T> source,
    IEqualityComparer<T> comparer)
{
    comparer = comparer ?? EqualityComparer<T>.Default;
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            return true;
        var first = iterator.Current;
        while (iterator.MoveNext())
            if (!comparer.Equals(first, iterator.Current))
                return false;
        return true;
    }
}

请注意,使用迭代器的显式枚举既可以防止序列多次迭代,也可以支持空序列。

另一种使用HashSet<Force>:

的有效方法
public bool IsUniform(ICollection<Force> forces)
{
    if (forces == null) throw new ArgumentNullException("forces");
    if (!forces.Any()) return false;
    var set = new HashSet<Force> { forces.First() };
    return set.SetEquals(forces);
}
// ...
bool allEqual = IsUniform(PointForceSet.Values);

可以工作,因为你已经覆盖了Equals + GetHashCode的注释

如果Force类覆盖EqualsGetHashCode方法,这应该可以工作。否则,实现IEqualityComparer并将其传递给构造函数

public bool IsUniform()
{    
    return new HashSet<Force>(PointForceSet.Values).Count == 1;
}