2009-09-10 27 views
116

MSDN giải thích Lookup như thế này:Điểm tra cứu <TKey, TElement> là gì?

Một Lookup<TKey, TElement> giống như một Dictionary<TKey, TValue>. Sự khác biệt là một điển < TKey, TValue > bản đồ chìa khóa để các giá trị duy nhất, trong khi một Lookup < TKey, TElement > bản đồ phím vào bộ sưu tập của các giá trị.

Tôi không thấy giải thích đó đặc biệt hữu ích. Lookup được sử dụng cho là gì?

Trả lời

172

Đó là một đường giao nhau giữa IGrouping và từ điển. Nó cho phép bạn nhóm các mục với nhau bằng một khóa, nhưng sau đó truy cập chúng thông qua khóa đó một cách hiệu quả (thay vì chỉ lặp qua tất cả chúng, đó là những gì GroupBy cho phép bạn làm).

Ví dụ, bạn có thể mất một tải của các loại NET và xây dựng một tra cứu bởi namespace ... sau đó nhận được cho tất cả các loại trong một không gian tên đặc biệt rất dễ dàng:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Xml; 

public class Test 
{ 
    static void Main() 
    { 
     // Just types covering some different assemblies 
     Type[] sampleTypes = new[] { typeof(List<>), typeof(string), 
            typeof(Enumerable), typeof(XmlReader) }; 

     // All the types in those assemblies 
     IEnumerable<Type> allTypes = sampleTypes.Select(t => t.Assembly) 
               .SelectMany(a => a.GetTypes()); 

     // Grouped by namespace, but indexable 
     ILookup<string, Type> lookup = allTypes.ToLookup(t => t.Namespace); 

     foreach (Type type in lookup["System"]) 
     { 
      Console.WriteLine("{0}: {1}", 
           type.FullName, type.Assembly.GetName().Name); 
     } 
    } 
} 

(Tôi thường . sử dụng var cho hầu hết các tờ khai, trong mã bình thường)

+43

Tôi nghĩ để làm cho câu trả lời này tốt hơn, bạn có thể thay thế một số lọ. Đối với mục đích học tập, tôi nghĩ rằng nó dễ dàng hơn để làm theo, khi các loại được thể hiện rõ ràng. Chỉ cần 2 xu của tôi :) –

+3

Nếu nó có tốt nhất của cả hai thế giới, thì tại sao phải bận tâm với một từ điển? –

+12

@KyleBaran: Bởi vì nó sẽ là vô nghĩa đối với bộ sưu tập cặp khóa/giá trị chính hãng, nơi chỉ có một giá trị cho mỗi khóa. –

11

tôi đã không thành công sử dụng nó trước đó, nhưng đây là đường đi của tôi:

một Lookup<TKey, TElement> sẽ hành xử khá giống như một (quan hệ) cơ sở dữ liệu chỉ mục trên một cái bàn không có một cái e ràng buộc. Sử dụng nó trong cùng một nơi bạn sẽ sử dụng khác.

51

Một cách để suy nghĩ về điều này là: Lookup<TKey, TElement> tương tự như Dictionary<TKey, Collection<TElement>>. Về cơ bản một danh sách các phần tử không hoặc nhiều hơn có thể được trả về thông qua cùng một khóa.

namespace LookupSample 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<string> names = new List<string>(); 
      names.Add("Smith"); 
      names.Add("Stevenson"); 
      names.Add("Jones"); 

      ILookup<char, string> namesByInitial = names.ToLookup((n) => n[0]); 

      // count the names 
      Console.WriteLine("J's: {0}", namesByInitial['J'].Count()); 
      Console.WriteLine("S's: {0}", namesByInitial['S'].Count()); 
      Console.WriteLine("Z's: {0}", namesByInitial['Z'].Count()); 
     } 
    } 
} 
+2

Có thể có 0 phần tử trong kết quả tra cứu không? Làm thế nào bạn sẽ có được điều đó? (Lookup là công khai bất biến như xa như tôi có thể nói, và tôi không nghĩ ToLookup có hiệu quả sẽ phát minh ra chìa khóa.) –

+8

Về mặt kỹ thuật, có, vì một Lookup trả về một bộ sưu tập trống cho một khóa không tồn tại (tôi đã sửa bài viết của tôi để thêm một mẫu mã cho thấy điều này). – bobbymcr

5

Tôi đoán bạn có thể tranh luận theo cách này: hãy tưởng tượng bạn đang tạo cấu trúc dữ liệu để giữ nội dung của sổ điện thoại. Bạn muốn khóa theo lastName và sau đó là firstName. Sử dụng một từ điển ở đây sẽ rất nguy hiểm vì nhiều người có thể có cùng tên. Vì vậy, một từ điển sẽ luôn luôn, nhiều nhất, ánh xạ tới một giá trị duy nhất.

Tra cứu sẽ ánh xạ tới nhiều giá trị tiềm năng.

Tra cứu ["Smith"] ["John"] sẽ là tập hợp có kích thước một tỷ.

+0

Câu trả lời của bạn đã truyền cảm hứng cho câu hỏi tiếp theo của tôi ["Cách thực hiện() với nhiều chỉ mục?"] (Http://stackoverflow.com/questions/15734454/how-tolookup-with-multiple-indexes). Làm thế nào tôi có thể tái sản xuất như vậy, với nhiều chỉ mục, tra cứu? Bạn có thể trả lời nó có thể sử dụng bất kỳ mẫu hoặc tham chiếu nào khác có thể sử dụng 'Lookup [" Smith "] [" John "]'? – Fulproof

17

Một lần sử dụng Lookup có thể đảo ngược một Dictionary.

Giả sử bạn có danh bạ được triển khai dưới dạng Dictionary với một nhóm (duy nhất) tên làm khóa, mỗi tên được liên kết với số điện thoại. Nhưng hai người có tên khác nhau có thể chia sẻ cùng một số điện thoại. Đây không phải là vấn đề đối với một số Dictionary, điều này không quan tâm hai khóa tương ứng với cùng một giá trị.

Bây giờ bạn muốn có cách tìm kiếm ai là số điện thoại cụ thể thuộc về. Bạn tạo Lookup, thêm tất cả KeyValuePairs từ Dictionary của bạn, nhưng ngược lại, với giá trị là khóa và khóa làm giá trị. Bây giờ bạn có thể truy vấn một số điện thoại và nhận danh sách tên của tất cả những người có số điện thoại.Xây dựng một Dictionary với cùng một dữ liệu sẽ thả dữ liệu (hoặc không, tùy thuộc vào cách bạn đã làm nó), vì làm

dictionary["555-6593"] = "Dr. Emmett Brown"; 
dictionary["555-6593"] = "Marty McFly"; 

có nghĩa là mục thứ hai ghi đè đầu tiên - Doc không còn được liệt kê.

Cố gắng viết cùng một dữ liệu theo một cách hơi khác nhau:

dictionary.Add("555-6593", "Dr. Emmett Brown"); 
dictionary.Add("555-6593", "Marty McFly"); 

sẽ ném một ngoại lệ trên dòng thứ hai kể từ khi bạn không thể Add một chìa khóa mà đã nằm trong Dictionary.

[Tất nhiên, bạn có thể muốn sử dụng một số cấu trúc dữ liệu khác để thực hiện tra cứu theo cả hai hướng, v.v. Ví dụ này có nghĩa là bạn phải tạo lại Lookup từ Dictionary mỗi lần thay đổi sau. Nhưng đối với một số dữ liệu, đó có thể là giải pháp phù hợp.]

Các vấn đề liên quan