2013-05-31 48 views
9

Tôi gặp sự cố khi nhận khóa bằng cách chỉ định giá trị. Cách tốt nhất tôi có thể đạt được điều này là gì?Lấy khóa từ giá trị - Từ điển <string, Danh sách <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; 

Trả lời

17

Giá trị trả về từ FirstOrDefault sẽ là một KeyValuePair<string, List<string>>, vì vậy để có được chìa khóa, chỉ cần sử dụng Key tài sản. Như thế này:

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

Ngoài ra, đây là tương đương trong cú pháp truy vấn:

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

Không phải là 'FirstOrDefault (...). Key' nguy hiểm, như trong hành vi bất ngờ khi "OrDefault" xảy ra ở đây ? –

+2

@ChrisMarisic Trường hợp 'OrDefault' trả về giá trị mặc định của loại bạn đang lặp lại. Đối với các kiểu tham chiếu, đó là 'null', nhưng đối với các kiểu giá trị, nó sẽ là một thể hiện mới của kiểu đó. Vì 'KeyValuePair ' là một kiểu giá trị (tức là một 'struct'), trường hợp 'OrDefault' sẽ không dẫn đến một ngoại lệ tham chiếu null. Vì 'TKey' ở đây là' chuỗi', '.Key' của cá thể mới đó sẽ là' null'. –

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

Nhưng nếu bạn đang tìm kiếm hiệu quả, tôi muốn đề nghị lùi từ điển của bạn và tạo ra một từ điển của <state, email> để làm những gì bạn đang tìm kiếm.

// 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

bất kỳ cách nào để xử lý 'NullReferenceException'? –

+0

Tôi không nghĩ như vậy, trong một lớp lót ít nhất. Đã chỉnh sửa bằng séc không phải LINQ. Nó thực hiện điều tương tự như LINQ thực hiện - lặp qua từng giá trị cho đến khi nó tìm thấy một giá trị, sau đó thoát khỏi vòng lặp. Nếu nó không bao giờ tìm thấy một, giá trị ban đầu của null được giữ lại. –

+1

Trên thực tế, nếu bạn đang nhận được một NullReferenceException, sau đó danh sách chính nó phải có được null. Bạn có thể xử lý điều đó bên trong lambda. Đã cập nhật. –

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

'KeyValuePair ' là một cấu trúc, do đó, 'temp' sẽ không bao giờ là rỗng. –

+0

Tôi có cùng một trường hợp sử dụng, nơi tôi có để có được giá trị khi key = [email protected] mệt mỏi dưới đây mà không cho đầu ra dự kiến. var emailAdd = statesToEmailDictionary.FirstOrDefault (x => x.Key == "[email protected]"). – Blossom

2

Tôi nghĩ rằng bạn muốn:

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

gì tất cả mọi người trong chủ đề này thất bại trong việc đề cập đến là phương pháp FirstOrDefault chỉ có sẵn thông qua 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

Simple LINQ để làm điều đó

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 

Tất nhiên nếu có những giá trị nhân bản này sẽ trở lại nhiều hơn một KeyValuePair

0
var emailAdd = statesToEmailDictionary.First(x=>x.Value.Contains(state)).Key; 
Các vấn đề liên quan