如何使用其他值从字典中获取值

时间:2019-05-01 18:11:14

标签: c#

我有问题。我创建了这样的字典:

tblproperties("skip.header.line.count"="1")

使用这样的课程:

var TriangleRegistry = new Dictionary<string, TriangleRegistryObject>();

字典中充满了三角形的坐标。现在,我知道x1,y1,x2,y2,x3,y3,并且我想使用x1,y1,x2,y2,x3,y3获得直角三角形的class TriangleRegistryObject { public double x1 { get; set; } public double y1 { get; set; } public double x2 { get; set; } public double y2 { get; set; } public double x3 { get; set; } public double y3 { get; set; } public bool Selected { get; set; } } 的值。
使用所有6个值找到第7个值很重要,因为我有很多三角形!
有人可以帮我吗?

3 个答案:

答案 0 :(得分:0)

如果您要存储和检索字典中的内容,并且键由三角形的所有三个坐标(六个值)组成,则三角形的组合坐标是的键字典。

这就是您在这里描述的内容:

  

我知道x1,y1,x2,y2,x3,y3,我想使用x1,y1,x2,y2,x3,y3来获取直角三角形的选定值。

(我回避了Dictionary<TriangleRegistryObject, bool>是否有意义的问题,而侧重于如何将三角形的点用作键。)

假设您实际上创建了一个Dictionary<TriangleRegistryObject, bool>,其中键是一个三角形,而值是一个布尔值,指示是否已选择它。挑战仍然是,为了确定键是否重复,字典将使用引用相等性。 TriangleRegistryObject的两个具有相同坐标的不同实例可以是两个键,这可能不是您想要的。

我们需要告诉字典如何比较两个三角形。我们可以通过在Equals上覆盖GetHashCodeTriangleRegistryObject来做到这一点。但是我们不必更改类以满足这种比较的需要,我们只需告诉此特定词典如何比较三角形即可(尽管这可能也是一个很好的解决方案。)

首先,我们将创建IEqualityComparer<TriangleRegistryObject>的自定义实现:

public class TriangleComparer : IEqualityComparer<TriangleRegistryObject>
{
    public bool Equals(TriangleRegistryObject x, TriangleRegistryObject y)
    {
        return x.x1.Equals(y.x1) 
               && x.y1.Equals(y.y1) 
               && x.x2.Equals(y.x2) 
               && x.y2.Equals(y.y2) 
               && x.x3.Equals(y.x3) 
               && x.y3.Equals(y.y3);
    }

    public int GetHashCode(TriangleRegistryObject obj)
    {
        unchecked
        {
            var hashCode = obj.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.GetHashCode();
            hashCode = (hashCode * 397) ^ obj.GetHashCode();
            return hashCode;
        }
    }
}

(好吧,这看起来并不那么简单。我实际上被骗了,让Resharper帮助我生成所有内容。)

现在,如果我们要使用三角形作为字典中的键,则只需在创建字典时指定比较器即可:

var dictionary = new Dictionary<TriangleRegistryObject, bool>(new TriangleComparer());

现在,字典将按照我们告诉它的方式比较键,而不是使用引用相等。

或者,如果您只是想将等式比较直接添加到三角形本身中,而不是使用自定义比较器,则可以执行此操作(该方法省去了Selected属性):

public class TriangleRegistryObject
{
    public double x1 { get; set; }
    public double y1 { get; set; }
    public double x2 { get; set; }
    public double y2 { get; set; }
    public double x3 { get; set; }
    public double y3 { get; set; }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    protected bool Equals(TriangleRegistryObject other)
    {
        return x1.Equals(other.x1) 
            && y1.Equals(other.y1) 
            && x2.Equals(other.x2) 
            && y2.Equals(other.y2) 
            && x3.Equals(other.x3) 
            && y3.Equals(other.y3);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = x1.GetHashCode();
            hashCode = (hashCode * 397) ^ y1.GetHashCode();
            hashCode = (hashCode * 397) ^ x2.GetHashCode();
            hashCode = (hashCode * 397) ^ y2.GetHashCode();
            hashCode = (hashCode * 397) ^ x3.GetHashCode();
            hashCode = (hashCode * 397) ^ y3.GetHashCode();
            return hashCode;
        }
    }
}

还有一个问题:三角形的点可能不会改变。如果他们可以改变,那么坏事就可能发生。假设您有两个不同的点用作键,然后将一个点更改为与另一个点相同。然后,您将有重复的密钥,这很不好。

为防止这种情况,您将使三角形类不可变,以便将值传递给构造函数,并且永远不能更改。


仅介绍基础知识,因为我不知道您的应用程序的任何细节:如果您的三角形是一个结构而不是一个类,并且其所有成员都是值类型,那么将使用值进行比较。如果唯一的值是点(删除Selected),则两个具有相同点的实例将被视为相等,并且不需要所有额外的比较代码。您仍然希望使该结构不可变。

答案 1 :(得分:0)

您可以使用LINQ(如上/下所述)或对每个循环进行此操作,并检查洗涤变量。在大多数情况下,LINQ的速度要慢得多,因此,如果您的应用程序需要更好的性能,请考虑将其用于/等。

答案 2 :(得分:-1)

您可以使用LINQ查询字典并找到匹配项:

using System.Linq;

...

var matches = TriangleRegistry.Where(t => t.Value.X1 == ... && t.Value.Y1 == ...); // fill in the blanks here with whatever you're looking for
foreach (var match in matches)
{
   Console.WriteLine("Here's a match: {0}", match.Selected);
}