Как проиндексировать свойство значений в словаре C # - PullRequest
2 голосов
/ 26 марта 2012

Используя свойство Values ​​из словаря C #,

var  myDict =  Dictionary < string, object> ;

Как получить значения в

  myDict.Values 

Я пытался

var theVales = myDict.Values ; 
object obj = theValues[0] ;

Но этосинтаксическая ошибка.

Добавлено: я пытаюсь сравнить значения в двух словарях с одинаковыми ключами

Ответы [ 4 ]

5 голосов
/ 26 марта 2012

Вы не можете.Значения не имеют фиксированного порядка.Вы можете записать значения в новый List<object> и индексировать их там, но, очевидно, это не очень полезно, если содержимое словаря часто меняется.

Вы также можете использовать linq: myDict.Values.ElementAt(0), но:

  • Элементы будут меняться по мере роста словаря
  • Это действительно неэффективно, поскольку он просто вызывает foreach для коллекции значений для заданного числа итераций.

Вы также можете использовать SortedList<TKey, TValue>.Это поддерживает значения в порядке согласно ключу, который может или не может быть тем, что вы хотите, и это позволяет вам получить доступ к значениям по ключу или по индексу.Однако в некоторых сценариях у него очень плохие характеристики производительности, поэтому будьте осторожны с этим!

Вот решение linq, позволяющее определить, совпадают ли значения для соответствующих ключей.Это работает, только если вы используете компаратор равенства по умолчанию для типа ключа.Если вы используете пользовательский компаратор равенства, вы можете сделать это с помощью синтаксиса вызова метода.

IEnumerable<bool> matches = 
    from pair1 in dict1
    join pair2 in dict2
        on pair1.Key equals pair2.Key
    select pair1.Value.Equals(pair2.Value)

bool allValuesMatch = matches.All();

Если вам требуется, чтобы все элементы в одном словаре имели соответствующий элемент в другом, вы можете сделать это:

bool allKeysMatch = new HashSet(dict1.Values).SetEquals(dict2.ValueS);
bool dictionariesMatch = allKeysMatch && allValuesMatch;
3 голосов
/ 26 марта 2012

Ну, вы могли бы использовать Enumerable.ElementAt, если бы вам действительно пришлось, но вы не должны ожидать, что заказ будет стабильным или значимым. Или позвоните ToArray или ToList, чтобы получить копию.

Обычно вы используете Values, только если собираетесь их перебирать. Что именно вы пытаетесь сделать здесь? Вы понимаете, что порядок записей в Dictionary<,> не определен?

РЕДАКТИРОВАТЬ: Похоже, вы хотите что-то вроде:

var equal = dict1.Count == dict2.Count &&
            dict1.Keys.All(key => ValuesEqual(key, dict1, dict2));

...
private static bool ValuesEqual<TKey, TValue>(TKey key,
    IDictionary<TKey, TValue> dict1,
    IDictionary<TKey, TValue> dict2)
{
    TValue value1, value2;
    return dict1.TryGetValue(out value1) && dict2.TryGetValue(out value2) &&
           EqualityComparer<TValue>.Default.Equals(value1, value2);
}

РЕДАКТИРОВАТЬ: обратите внимание, что это не так быстро, как могло бы быть, потому что он выполняет поиск в обоих словарях. Это было бы более эффективным, но менее элегантным ИМО:

var equal = dict1.Count == dict2.Count &&
            dict1.All(pair  => ValuesEqual(pair.Key, pair.Value, dict2));

...
private static bool ValuesEqual<TKey, TValue>(TKey key, TValue value1,
    IDictionary<TKey, TValue> dict2)
{
    TValue value2;
    return dict2.TryGetValue(out value2) &&
           EqualityComparer<TValue>.Default.Equals(value1, value2);
}
1 голос
/ 26 марта 2012

Чтобы добавить ответ @ JonSkeet, Dictionary<TKey, TValue> поддерживается HashTable, который представляет собой неупорядоченную структуру данных. Таким образом, указатель значений не имеет смысла - вполне допустимо получить, скажем, A,B,C с одним вызовом и C,B,A с другим.

EDIT:

На основании вашего комментария к ответу JS («Я пытаюсь сравнить значения в двух словарях с одинаковыми ключами»), вы хотите что-то вроде этого:

public boolean DictionariesContainSameKeysAndValues<TKey, TValue>(Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue> dict2) {
    if (dict1.Count != dict2.Count) return false;
    for (var key1 in dict1.Keys)
        if (!dict2.ContainsKey(key1) || !dict2[key1].Equals(dict1[key1]))
            return false;
    return true;
}
0 голосов
/ 19 ноября 2013

Вы можете использовать свойство Indexer для поиска строки Key.Это еще не Индекс, а еще один способ:

using System.Collections.Generic;
...
class Client
{
   private Dictionary<string, yourObject> yourDict 
      = new Dictionary<string, yourObject>();

   public void Add (string id, yourObject value)
      { yourDict.Add (id, value); }

   public string this [string id]      // indexer
   {
   get { return yourDict[id]; }
   set { yourDict[id] = value; }
   }
}

public class Test
{
   public static void Main( )
   {
      Client client = new Client();
      client.Add("A1",new yourObject() { Name = "Bla",...);
      Console.WriteLine ("Your result: " + client["A1"]); // indexer access
    }   
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...