2009-06-10 8 views

Odpowiedz

5

Jeśli twoje "nazwiska" są łatwo określone z twojego "T", sugeruję KeyedCollection.

Działa jak List, ponieważ można wyszukiwać elementy według indeksów. Ale działa również jak słownik, ponieważ wewnętrznie używa słownika do mapowania nazw (kluczy) do odpowiedniego indeksu i zapewnia indeksator dla twojego typu klucza.


Zapytałeś, skąd wie, czego użyć do klucza. KeyedCollection to klasa abstrakcyjna, którą musisz dziedziczyć. Na szczęście łatwo to zrobić. Jedyną metodą przeciążenia jest GetKeyForItem(). Ta metoda jest odpowiedzią na twoje pytanie. Na przykład, weźmy tę prostą klasę:

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

Można wdrożyć KeyedCollection tak:

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 

To wszystko jest do niego. Masz teraz kolekcję, która będzie działać jak słownik lub lista. Jest jeszcze potężniejszy, gdy można używać generycznych lub innych interfejsów, aby uniknąć powiązania klasy z konkretnym typem.

+0

jak określa, która właściwość lub pole na obiekcie będzie kluczem? – Maslow

+0

'KeyedCollection' jest klasą abstrakcyjną, którą musisz dziedziczyć. Na szczęście łatwo to zrobić. Jedyną metodą przeciążania jest 'GetKeyForItem()'. Ta metoda jest odpowiedzią na twoje pytanie. –

+0

Awesome, myślę, że to zadziała. – Maslow

-1

myślę szukasz System.Collections.Hashtable :)

+0

Nr HashTable jest w zasadzie pre-generic forma Słownik . Maslow (jak sądzę) szuka się wielojęzycznego słownika, którego nie ma w rdzeniowej strukturze. –

+0

Pokonaj mnie. Właśnie to zamierzałem powiedzieć. – ryanulit

+0

Nie widzę sposobu na indeksowanie tego przez liczbę całkowitą, a to nie jest ogólne. Pomyślałem, że z mojego rozumienia haseł, że hashtable powinien być dokładnie tym, czego chcę, ale do tej pory odkryłem System.Collections.Hashtable brakuje indeksowania i bezpieczeństwa typu. – Maslow

7

myślę System.Collections.Specialized.OrderedDictionary jest to, czego szukasz.

+0

Jest to rodzaj wielopunktowego zestawu specjalnego; szkoda, że ​​BCL nie ma ogólnego przeznaczenia. – Charlie

+0

OrderedDictionary pozwoli ci indeksować według liczby całkowitej lub obiektu, który się pojawi? Nie lubię zajmować się boksowaniem/rozpakowywaniem stałego rzucania, ale przypuszczam, że w niektórych przypadkach może to działać. – Maslow

+0

OrderedDictionary umożliwia użycie indeksu całkowitego lub * obiektu *. Jest starszy od generycznych, więc kluczem i wartością są typy obiektów. Można użyć kilku słowników (jeden słownik dla indeksów i słownik dla kluczy) i ręcznie zachować synchronizację. Ugodziłbym się z OrderedDictionary i boksowaniem;) –

-1

Czy dostęp do listy T według indeksu (lista < List < T >>) wystarczająco dobre?

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

, która nie pozwala mi odwoływać się do foo według nazwy/ciągu znaków. – Maslow

+0

Być może odpowiedziałem zbyt dosłownie? Przechowuje listy (nie tablice, stąd moje pytanie, czy to wystarczające) i pozwala uzyskać listę w określonym (numerycznym) "indeksie". Kiedy powiedziałeś "indeks lub nazwę", zinterpretowałem to jako "int lub string". Zgaduję, że to był błąd? – lance

+0

Nie, chcę listę T, do której odwołuje się int lub string. ale lista listy T nie byłaby indeksowana przez ciąg znaków, to jest 2 poziomy int? – Maslow

0

Wygląda na to, że potrzebny jest multimap, ale niestety nie ma zastosowania ogólnego w tym celu w BCL. Jak wspomniano w innej odpowiedzi, System.Collections.Specialized.OrderedDictionary jest specyficzną implementacją, która może zaspokoić twoje potrzeby, chociaż nie używa generycznych.

1

Specjalistyczna wersja OrderedDictionary nie jest ogólna.

Można zastosować ogólny interfejs słownika z niestandardową klasą GenericOrderedDictionary.

Masz prywatny

List<TKey>
i prywatny
List<TValue>
.

Visual Studio może zaimplementować metody interfejsu użytkownika.

Początek to będzie wyglądać:


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

Jeśli masz tablicę T, można generować wiele słowników z tej tablicy przez wywołanie ToDictionary i żywienia w różnych właściwościach T.

Przypuśćmy, że T jest klient:

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

Myślę, że coś takiego jest najbliżej, co chcesz:

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

Po prostu bierzesz zwykły słownik <> i dodajesz możliwość indeksowania według int.

Edit: Mehrdad podnosi dobry punkt, że moja metoda IndexDictionary.Add(TKey, TValue) może spowodować wkładką raczej niż dołączyć. Jeśli to będzie powodować problemy w danej sytuacji, to chciałbym zaproponować coś takiego:

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 
    } 

To daje zleceniem zachowaniu korzyści OrderedDictionary z bezpieczeństwem typu Dictionary<TKey, TValue>.

+0

Kolejność klawiszy nie jest jednak gwarantowana. Mogą się zmieniać wraz z dodawaniem lub usuwaniem nowych elementów. –

0

To co mam teraz testuje większość funkcji została automatycznie uzupeĹ,nianych w dla mnie, kiedy wdrożone 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 

Class End

Powiązane problemy