2013-05-31 13 views
9

Mam problem z uzyskaniem klucza przez podanie wartości. Jaki jest najlepszy sposób, w jaki mogę to osiągnąć?Uzyskaj klucz z wartości - Słownik <ciąg, lista <string>>

var st1= new List<string> { "NY", "CT", "ME" }; 
var st2= new List<string> { "KY", "TN", "SC" }; 
var st3= new List<string> { "TX", "OK", "MO" }; 
var statesToEmailDictionary = new Dictionary<string, List<string>>(); 
statesToEmailDictionary.Add("[email protected]", st1); 
statesToEmailDictionary.Add("[email protected]", st2); 
statesToEmailDictionary.Add("[email protected]", st3); 

var emailAdd = statesToEmailDictionary.FirstOrDefault(x => x.Value.Where(y => y.Contains(state))).Key; 

Odpowiedz

17

Wartość zwracana z FirstOrDefault będzie KeyValuePair<string, List<string>>, tak aby dostać klucz, wystarczy użyć właściwości Key. Tak:

var emailAdd = statesToEmailDictionary 
    .FirstOrDefault(x => x.Value.Contains(state)) 
    .Key; 

Alternatywnie, tutaj jest równoważne w składni zapytania:

var emailAdd = 
    (from p in statesToEmailDictionary 
    where p.Value.Contains(state) 
    select p.Key) 
    .FirstOrDefault(); 
+0

nie jest 'FirstOrDefault (...). Key' niebezpieczne, jak nieoczekiwane zachowanie w przypadku wystąpienia„OrDefault”tutaj ? –

+2

@ChrisMarisic Przypadku "OrDefault" zwraca wartość domyślną typu, który jest iteracyjne. W przypadku typów odniesienia jest to 'null', ale w przypadku typów wartości będzie to nowe wystąpienie tego typu. Ponieważ 'KeyValuePair ' jest typem wartości (tj. 'Struct'), przypadek" OrDefault "nie spowoduje wyjątku dotyczącego odwołania zerowego. Ponieważ 'TKey' tutaj to' string', '.Key' tej nowej instancji będzie' null'. –

1
var emailAdd = statesToEmailDictionary 
    .FirstOrDefault(x => x.Value != null && x.Value.Contains(state)) 
    .Key; 

Ale jeśli szukasz wydajności, sugeruję odwrócenie słownika oraz tworzenia słownika <state, email>, aby zrobić to, czego szukasz.

// To handle when it's not in the results 
string emailAdd2 = null; 
foreach (var kvp in statesToEmailDictionary) 
{ 
    if (kvp.Value != null && kvp.Value.Contains(state)) 
    { 
     emailAdd2 = kvp.Key; 
     break; 
    } 
} 
+0

jakikolwiek sposób obsługi 'NullReferenceException'? –

+0

Nie sądzę, przynajmniej w jednym liniowcu. Edytowano za pomocą sprawdzenia innego niż LINQ. Robi to samo, co LINQ - pętle przechodzą przez każdą wartość, aż znajdzie jedną, a następnie wyłączy się z pętli. Jeśli go nigdy nie znajdzie, zostanie zachowana pierwotna wartość pusta. –

+1

W rzeczywistości, jeśli otrzymujesz wyjątek NullReferenceException, sama lista musi mieć wartość zerową. Możesz sobie z tym poradzić w lambda. Zaktualizowano. –

-1
var temp = statesToEmailDictionary.Where(x => x.Value.Contains(state)).FirstOrDefault(); 
var emailAdd = temp != null ? temp.Key : string.Empty; 
+1

'KeyValuePair ' jest strukturą, więc 'temp' nigdy nie będzie mieć wartości NULL. –

+0

Mam ten sam przypadek użycia, gdzie muszę uzyskać wartość, gdy klucz = [email protected] Mam zmęczenie poniżej, który nie daje oczekiwanych wyników. var emailAdd = statesToEmailDictionary.FirstOrDefault (x => x.Key == "[email protected]"). Wartość; – Blossom

2

Myślę, że chcesz:

var emailAdd = statesToEmailDictionary.FirstOrDefault(x => x.Value.Any(y => y.Contains(state))).Key; 
1

Co każdy w tym wątku nie wspomnieć, że metoda FirstOrDefault jest dostępna tylko poprzez Linq:

using System; 
using System.Collections.Generic; 
// FirstOrDefault is part of the Linq API 
using System.Linq; 

namespace Foo { 
    class Program { 
     static void main (string [] args) { 
      var d = new Dictionary<string, string>() { 
       { "one", "first" }, 
       { "two", "second" }, 
       { "three", "third" } 
      }; 
      Console.WriteLine (d.FirstOrDefault (x => x.Value == "second").Key); 
     } 
    } 
} 
0

Proste Linq aby to zrobić,

Dim mKP = (From mType As KeyValuePair(Of <Key type>, <Value type>) In <Dictionary> 
      Where mType.Value = <value seeked> Select mType).ToList 

If mKP.Count > 0 then 
    Dim value as <value type> = mKP.First.Value 
    Dim key as <Key type> = mKP.First.Key 
End if 

Oczywiście, jeśli istnieją zduplikowane wartości to zwróci więcej niż jeden KeyValuePair

0
var emailAdd = statesToEmailDictionary.First(x=>x.Value.Contains(state)).Key; 
Powiązane problemy