2016-05-19 1 views
1

Дано:Transform словарь к другому с другим типом ключа

class KeyType1{...} 
class KeyType2{...} 
class ValueType{...} 

public KeyType2 Lookup(KeyType1 value) 
{ 
    // Returns a unique value of KeyType2 or otherwise, null 
} 

Есть ли аккуратный LINQ способ преобразования:

IDictionary<KeyType1,ValueType> ==>IDictionary<KeyType2,ValueType>

следующие важные моменты:

  • № 2 значения KeyType1 показать на карте KeyType2
  • Редактировать Возможно, Lookup может возвращать null, т. Е. Отображение может быть неполным. В таких случаях эти записи должны быть исключены из нового словаря
+0

Примечание: редактирование: 'Lookup' может возвращать null –

+0

Обновлен мой ответ. Сложно изменить требования после того, как люди уже ответили. Я только случайно прочитал эту новую проблему (нулевой возвращаемый Lookup). Если дальнейшие изменения произойдут, пожалуйста, оставьте мне комментарий :) –

+0

Да, я добавил его сразу после этого, я ждал, чтобы люди заметили, а не опубликовали тот же комментарий по 3 ответам (все они были даны очень быстро) –

ответ

1

ok, предполагается, что Lookup - это функция, которая возвращает ссылочный тип, который может быть нулевым.

b = a 
    .Select(p => new { Key = Lookup(p.Key), p.Value })) 
    .Where(p => p.Key != null) 
    .ToDictionary(p => p.Key, p => p.Value); 
1

Чтобы избежать нуждаться Lookup дважды вы можете, во-первых создать Dictionary<KeyType1, KeyType2> на карту старых ключей к новому:

IDictionary<KeyType1,KeyType2> keyMap = sourceDictionary.Keys.ToDictionary(key => key, key => Lookup(key)); 

Это keyMap теперь может содержать значения null для некоторых ключей источника. Таким образом, мы фильтруем его Where, а затем объединить их с исходным словарем, чтобы создать новый словарь:

IDictionary<KeyType2,ValueType> target = keyMap.Where(kvp => kvp.Value != null). 
       ToDictionary(kvp => kvp.Value, sourceDictionary[kvp.Key]); 
0
Dictionary<string, string> StringDict = new Dictionary<string, string>(); 
Dictionary<int, string> IntDict = new Dictionary<int, string>(); 


StringDict.ToList().ForEach(D => 
{ 
    IntDict.Add(Convert.ToInt32(D.Key), D.Value); 
}); 
1

Вы можете использовать Where, во-первых, чтобы отфильтровать источник, а затем использовать ToDictionary расширения с указанием нового ключа и значение:

var dictionary1 = new Dictionary<KeyType1, ValueType>(); 
var dictionary2 = dictionary1.Where(kv => Lookup(kv.Key) != null) 
          .ToDictionary(kv => Lookup(kv.Key), kv => kv.Value); 

Если вы хотите, чтобы вычислить ключ для тех случаев, когда Lookup является null вы можете сделать это:

dictionary1.ToDictionary(kv => Lookup(kv.Key) ?? ComputeNewKey(kv.Key), 
         kv => kv.Value);