У меня проблема. Я создал словарь, как это:

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

С таким классом:

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; }
}

Словарь заполнен координатами треугольников. Теперь я знаю x1, y1, x2, y2, x3, y3 и хочу получить значение Selected прямоугольного треугольника, используя x1, y1, x2, y2, x3, y3.
Важно, чтобы я использовал все 6 значений, чтобы найти 7-е, потому что у меня много треугольников!
Кто-нибудь может мне помочь?

c#
0
Vreesie 1 Май 2019 в 21:11

3 ответа

Лучший ответ

Если вы хотите сохранить и извлечь что-то из словаря, а ключ состоит из всех трех координат треугольника - шести значений - тогда объединенные координаты треугольника являются ключом к словарю.

Вот что вы здесь описываете:

Я знаю x1, y1, x2, y2, x3, y3, и я хочу получить значение Selected правого треугольника, используя x1, y1, x2, y2, x3, y3.

(Я обошел вопрос, имеет ли смысл Dictionary<TriangleRegistryObject, bool>, и сосредоточился на том, как точки треугольника можно использовать в качестве ключа.)

Предположим, вы действительно создали Dictionary<TriangleRegistryObject, bool>, где ключ был треугольником, а значение - логическим значением, указывающим, был ли он выбран или нет. Проблема все равно будет заключаться в том, что для определения того, является ли ключ дубликатом, словарь будет использовать равенство ссылок. Два разных экземпляра TriangleRegistryObject с одинаковыми координатами могут быть двумя ключами, что, вероятно, не то, что вам нужно.

Нам нужно рассказать в словаре, как сравнивать два треугольника. Мы могли бы сделать это, переопределив Equals и GetHashCode в TriangleRegistryObject. Но вместо того, чтобы изменить класс для удовлетворения потребностей этого сравнения, мы можем просто сказать этому конкретному словарю, как сравнивать треугольники (хотя это также может быть вполне хорошим решением).

Сначала мы создадим пользовательскую реализацию 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;
        }
    }
}

(Хорошо, это не выглядит так просто. Я на самом деле обманул и позволил Решарперу помочь мне сгенерировать все это.)

Теперь, если мы хотим использовать треугольник в качестве ключа в словаре, мы просто указываем этот компаратор при создании словаря:

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), тогда два экземпляра с одинаковыми точками будут считаться равными, и вам не потребуется весь дополнительный код сравнения. Вы все еще хотели бы сделать структуру неизменной.

0
Scott Hannen 1 Май 2019 в 20:03

Вы можете использовать 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);
}
-1
Judah Gabriel Himango 3 Май 2019 в 21:05

Вы можете сделать это с помощью LINQ (как указано выше / ниже) или для каждой петли и проверить переменную стирки. В большинстве случаев LINQ работает медленнее, поэтому, если вашему приложению требуется более высокая производительность, рассмотрите возможность использования для каждого / и т. Д.

0
Iv Misticos 2 Май 2019 в 07:38