2009-06-10 53 views

Trả lời

5

Nếu "tên" của bạn dễ dàng được xác định từ "T", tôi đề xuất KeyedCollection.

Nó hoạt động như List, trong đó bạn có thể tìm kiếm các mục theo chỉ mục. Nhưng nó cũng hoạt động như một từ điển, trong đó nó sử dụng một từ điển nội bộ để ánh xạ các tên (các khóa) đến chỉ mục thích hợp và cung cấp một bộ chỉ mục cho loại khóa của bạn.


Bạn đã hỏi cách thức sử dụng khóa này. KeyedCollection là lớp trừu tượng mà bạn phải thừa hưởng. May mắn thay, thật dễ dàng để làm. Phương pháp duy nhất bạn cần quá tải là GetKeyForItem(). Phương pháp đó là câu trả lời cho câu hỏi của bạn. Ví dụ, hãy lớp đơn giản này:

Public Class MyClass 
    Public UniqueID As Guid 
    Public OtherData As String 
End Class 

Bạn có thể thực hiện KeyedCollection như thế này:

Public Class MyClassCollection 
    Inherits KeyedCollection(Of Guid, MyClass) 

    Public Overrides Function GetKeyForItem(ByVal item As MyClass) As Guid 
     Return item.UniqueID 
    End Function 
End Class 

Đó là tất cả để có nó. Bây giờ bạn có một bộ sưu tập sẽ hoạt động như một từ điển hoặc một danh sách. Nó thậm chí còn mạnh mẽ hơn khi bạn có thể sử dụng generics hoặc các giao diện khác để tránh buộc các lớp vào một loại cụ thể.

+0

làm cách nào để xác định thuộc tính hoặc trường nào trên đối tượng sẽ là khóa? – Maslow

+0

'KeyedCollection' là một lớp trừu tượng mà bạn phải thừa hưởng. May mắn thay, thật dễ dàng để làm. Phương thức duy nhất bạn cần để quá tải là 'GetKeyForItem()'. Phương pháp đó là câu trả lời cho câu hỏi của bạn. –

+0

Tuyệt vời, tôi nghĩ rằng điều này sẽ làm việc. – Maslow

-1

Tôi nghĩ rằng bạn đang tìm kiếm System.Collections.Hashtable :)

+0

số HashTable về cơ bản là hình thức tiền chung của một từ điển . Maslow (Tôi tin) được tìm kiếm một từ điển có thể lập chỉ mục, không tồn tại trong khung cốt lõi. –

+0

Đánh tôi với nó. Đó là những gì tôi định nói. – ryanulit

+0

Tôi không thấy cách lập chỉ mục theo số nguyên và không phải là chung. Tôi nghĩ từ sự hiểu biết của tôi về hashtables rằng một hashtable nên được chính xác những gì tôi muốn, nhưng cho đến nay những gì tôi đã khám phá của System.Collections.Hashtable nó thiếu lập chỉ mục và loại an toàn. – Maslow

7

Tôi nghĩ System.Collections.Specialized.OrderedDictionary là những gì bạn đang tìm kiếm.

+0

Đây là một loại multimap đặc biệt; quá xấu BCL không có mục đích chung. – Charlie

+0

OrderedDictionary sẽ cho phép bạn lập chỉ mục theo số nguyên hoặc đối tượng nó xuất hiện? Tôi không thích đối phó với boxing/unboxing đúc liên tục, nhưng tôi cho rằng nó có thể làm việc trong một số trường hợp. – Maslow

+0

OrderedDictionary cho phép bạn sử dụng chỉ số nguyên hoặc phím * đối tượng *. Nó lớn hơn so với generics đến xung quanh nên cả khóa và giá trị đều là các kiểu đối tượng. Bạn có thể sử dụng một vài từ điển (một từ điển cho chỉ mục và một từ điển cho khóa) và đồng bộ hóa chúng theo cách thủ công. Tôi sẽ giải quyết với OrderedDictionary và boxing mặc dù;) –

-1

Đang truy cập danh sách T theo chỉ mục (Danh sách < Danh sách < T >>) đủ tốt?

List<List<foo>> list = new List<List<foo>>(); 
List<foo> firstList = list[0]; 
+0

không xuất hiện để tôi tham chiếu foo theo tên/chuỗi. – Maslow

+0

Có lẽ tôi đã trả lời đúng theo nghĩa đen? Nó lưu trữ danh sách (không phải mảng, do đó yêu cầu của tôi nếu đó là đủ) và cho phép bạn có được một danh sách tại một chỉ số (số) "chỉ định". Khi bạn nói "chỉ mục hoặc tên", tôi giải thích rằng đó là "int hoặc chuỗi". Tôi đoán đó là một sai lầm? – lance

+0

không, tôi muốn danh sách T được tham chiếu bởi int hoặc chuỗi. nhưng một danh sách các danh sách của T sẽ không được lập chỉ mục theo chuỗi, đó là một int cấp 2? – Maslow

0

Có vẻ như bạn cần multimap, nhưng rất tiếc, không có mục đích chung nào được thực hiện trong BCL này. Như đã đề cập trong một câu trả lời khác, System.Collections.Specialized.OrderedDictionary là một triển khai cụ thể có thể đáp ứng nhu cầu của bạn, mặc dù nó không sử dụng Generics.

1

Phiên bản chuyên biệt của OrderedDictionary không phải là chung chung.

Bạn có thể triển khai giao diện Từ điển chung với lớp GenericOrderedDictionary tùy chỉnh.

Có riêng

List<TKey>
và riêng tư
List<TValue>
.

Visual Studio có thể cung cấp các phương thức giao diện cho bạn.

Sự bắt đầu của nó sẽ như thế nào:


public class GenericOrderedDictionary< TKey, TValue > 
    : IDictionary<TKey, TValue> 
{ 
    private List<TKey> keys; 
    private List<TValue> values; 

    #region IDictionary<TKey,TValue> Members 

    void IDictionary<TKey, TValue>.Add(TKey key, TValue value) 
    { 
     keys.Add(key); 
     values.Add(value); 
    } 

    bool IDictionary<TKey, TValue>.ContainsKey(TKey key) 
    { 
     return keys.Contains(key); 
    } 

    ICollection<TKey> IDictionary<TKey, TValue>.Keys 
    { 
     get 
     { 
      return new List<TKey>(keys); 
     } 
    } 

    bool IDictionary<TKey, TValue>.Remove(TKey key) 
    { 
     int index = keys.IndexOf(key); 
     if (index >= 0) 
     { 
      keys.Remove(key); 
      values.RemoveAt(index); 
     } 
    } 

0

Nếu bạn có một mảng của T, bạn có thể tạo ra nhiều từ điển từ mảng này bằng cách gọi ToDictionary và ăn trong các thuộc tính khác nhau của T.

giả sử T là khách hàng:

Customer[] myCustomers = getArray(); 
Dictionary<int, Customer> byID = myCustomers 
    .ToDictionary(c => c.ID); 
Dictionary<string, Customer> byName = myCustomers 
    .ToDictionary(c => c.Name); 
Dictionary<int, Customer> byOriginalPosition = myCustomers 
    .Select((c, i) => new {c, i}) 
    .ToDictionary(x => x.i, x => x.c); 
2

tôi nghĩ rằng một cái gì đó như thế này là gần nhất với những gì bạn muốn:

class IndexDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
    { 
    public TValue this[int i] 
    { 
     get { return this[Keys.ElementAt(i)]; } 
     set { this[Keys.ElementAt(i)] = value; } 
    } 
    } 

Bạn chỉ đang dùng từ điển thông thường <> và thêm khả năng lập chỉ mục theo int.

Sửa: Mehrdad đặt ra một điểm tốt, rằng phương pháp IndexDictionary.Add(TKey, TValue) tôi có thể dẫn đến một chèn chứ không phải là một thêm. Nếu điều đó sẽ gây ra vấn đề trong tình huống của bạn, sau đó tôi sẽ đề nghị một cái gì đó như thế này:

class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
    { 
    private OrderedDictionary data = new OrderedDictionary(); 

    public TValue this[int i] 
    { 
     get { return (TValue)data[i]; } 
     set { data[i] = value; } 
    } 

    //Implement IDictionary<TKey, TValue> using the methods of the OrderedDictionary 
    } 

này mang đến cho bạn những lợi ích để bảo quản các OrderedDictionary với loại an toàn của Dictionary<TKey, TValue>.

+0

Thứ tự của các khóa không được đảm bảo. Chúng có thể thay đổi khi các phần tử mới được thêm hoặc xóa. –

0

Đây là những gì tôi đang thử nghiệm bây giờ hầu hết các chức năng được tự động điền vào cho tôi khi tôi thực hiện IDictionary

Public Class bDictionary(Of TKey, TVAlue) 
Implements IDictionary(Of TKey, TVAlue) 

Private dictionary As New Dictionary(Of TKey, TVAlue) 
Private list As List(Of TKey) 

Default Public Property Item(ByVal which As TKey) As TVAlue Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Item 
    Get 
     Return dictionary(which) 
    End Get 
    Set(ByVal value As TVAlue) 
     dictionary(which) = value 
    End Set 
End Property 

Default Public Property Item(ByVal index As Integer) As TVAlue 
    Get 
     Return dictionary(list(index)) 
    End Get 
    Set(ByVal value As TVAlue) 
     dictionary(list(index)) = value 
    End Set 
End Property 

Public Sub Add(ByVal key As TKey, ByVal value As TVAlue) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Add 
    dictionary.Add(key, value) 
    list.Add(key) 
End Sub 

Public Sub Add(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Add 
    Add(item.Key, item.Value) 
End Sub 

Public Sub Clear() Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Clear 
    dictionary.Clear() 
    list.Clear() 
End Sub 

Public Function Contains(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Contains 
    If dictionary.ContainsKey(item.Key) AndAlso dictionary(item.Key).Equals(item.Value) Then 
     Return True 
    Else 
     Return False 
    End If 

End Function 


Public ReadOnly Property Count() As Integer Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Count 
    Get 
     Return list.Count 
    End Get 
End Property 

Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).IsReadOnly 
    Get 
     Return False 
    End Get 
End Property 

Public Function Remove(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Remove 
    Return Remove(item.Key) 
End Function 

Public Function ContainsKey(ByVal key As TKey) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).ContainsKey 
    Return list.Contains(key) 
End Function 

Public ReadOnly Property Keys() As System.Collections.Generic.ICollection(Of TKey) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Keys 
    Get 
     Return dictionary.Keys 
    End Get 
End Property 

Public Function Remove(ByVal key As TKey) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Remove 
    If list.Contains(key) Then 
     list.Remove(key) 
     dictionary.Remove(key) 
     Return True 
    Else 
     Return False 
    End If 
End Function 

Public Function TryGetValue(ByVal key As TKey, ByRef value As TVAlue) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).TryGetValue 
    Return dictionary.TryGetValue(key, value) 
End Function 

Public ReadOnly Property Values() As System.Collections.Generic.ICollection(Of TVAlue) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Values 
    Get 
     Return dictionary.Values 
    End Get 
End Property 


Public Sub CopyTo(ByVal array() As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue), ByVal arrayIndex As Integer) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).CopyTo 

    For Each Item As TKey In dictionary.Keys 
     array.SetValue(New KeyValuePair(Of TKey, TVAlue)(Item, dictionary(Item)), arrayIndex) 
     arrayIndex += 1 
    Next 

End Sub 

Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator 
    Return dictionary.GetEnumerator() 
End Function 

Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) Implements System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).GetEnumerator 
    Return dictionary.GetEnumerator 
End Function 

End Class

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