„Tuples“ (arba masyvai) kaip žodynų klavišai „C“

Bandau padaryti žodynų paieškos lentelę C #. Turiu leisti 3 eilutes reikšmių vienai eilutei. Bandžiau naudoti masyvus kaip raktus, bet tai neveikė, ir aš nežinau, ką dar daryti. Šiuo metu apsvarstysiu galimybę kurti žodynų žodyną žodynais, bet tikriausiai tai nėra labai malonu pažvelgti, nors norėčiau tai padaryti javascript'e.

85
05 июня '09 в 16:56 2009-06-05 16:56 AlexH yra nustatytas birželio 05 '09, 16:56 2009-06-05 16:56
@ 7 atsakymai

Jei naudojate .NET 4.0, naudokite Tuple:

 lookup = new Dictionary<Tuple<TypeA, TypeB, TypeC>, string>(); 

Jei ne, galite nustatyti paketą ir naudoti jį kaip raktą. Tuple turėtų nepaisyti „GetHashCode“, „Equals“ ir „IEquatable“:

 struct Tuple<T, U, W> : IEquatable<Tuple<T,U,W>> { readonly T first; readonly U second; readonly W third; public Tuple(T first, U second, W third) { this.first = first; this.second = second; this.third = third; } public T First { get { return first; } } public U Second { get { return second; } } public W Third { get { return third; } } public override int GetHashCode() { return first.GetHashCode() ^ second.GetHashCode() ^ third.GetHashCode(); } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) { return false; } return Equals((Tuple<T, U, W>)obj); } public bool Equals(Tuple<T, U, W> other) { return other.first.Equals(first)  other.second.Equals(second)  other.third.Equals(third); } } 
94
05 июня '09 в 17:06 2009-06-05 17:06 atsakymą pateikė Hallgrim birželio 5 d., 09:17, 2009-06-05 17:06

Sąveika tarp paketo ir įterptųjų žodynų beveik visada geriau tinka rinkiniams.

Kalbant apie tinkamumą naudoti ,

  • Tai daug lengviau įdiegti tokias funkcijas:

     var myDict = new Dictionary<Tuple<TypeA, TypeB, TypeC>, string>(); 

    nei

     var myDict = new Dictionary<TypeA, Dictionary<TypeB, Dictionary<TypeC, string>>>(); 

    skambinančioji šalis. Antruoju atveju kiekvienas papildymas, paieška, ištrynimas ir kt. Reikalingi veiksmai daugiau nei vienam žodynui.

  • Be to, jei jūsų sudėtiniam raktui ateityje reikės kitų (ar mažiau) laukų, antruoju atveju turėsite pakeisti reikšmingą kodo dalį (įterptą žodyną), nes jums reikia pridėti papildomų įterptųjų žodynų ir vėlesnius patikrinimus.

Kalbant apie efektyvumą, geriausias rezultatas, kurį galite pasiekti, yra įvertinti save. Tačiau yra keletas teorinių apribojimų, kuriuos galite iš anksto apsvarstyti:

  • Įdėto žodyno atveju papildomo žodyno buvimas kiekvienam klavišui (išoriniam ir vidiniam) turės tam tikrą atminties viršutinę vertę (be to, kas bus sukurta).

  • Įdėto žodyno atveju kiekvienas pagrindinis veiksmas, pvz., Papildymas, atnaujinimas, paieška, ištrynimas ir kt., Turi būti atliekamas dviejuose žodynuose. Dabar yra atvejis, kai įdėtos kalbos žodynas gali būti greitesnis, t.y. Kai duomenų nėra, nes tarpiniai žodynai gali apeiti pilno maišos kodo apskaičiavimą ir palyginimą, bet tai vėl turėtų būti reikalinga. Jei yra duomenų, ji turėtų būti lėčiau, nes paieška turėtų būti atliekama du kartus (arba tris kartus, priklausomai nuo lizdų).

  • Kalbant apie „tuple“ metodą, „.NET“ paketai nėra efektyviausi, kai jie skirti naudoti kaip raktai rinkiniuose, nes jos „ Equals ir „ GetHashCode diegimas vadina vertės tipų > .

Norėčiau eiti naudodamas žodyną „tuple“, bet jei norėčiau gauti daugiau rezultatų, naudodamasis geresniu įgyvendinimu, naudoju savo rinkinį.


Šoninėje pastaboje keletas kosmetikos gaminių gali padaryti žodyną kietą:

  • Skambinimas į indeksavimo stilių gali būti daug švaresnis ir intuityvesnis. Pavyzdžiui

     string foo = dict[a, b, c]; //lookup dict[a, b, c] = ""; //update/insertion 

    Todėl nustatykite reikiamus savo žodyno indeksus, kurie viduje tvarko intarpus ir paieškas.

  • Taip pat sukurkite tinkamą „ IEnumerable sąsają ir pateikite „ Add(TypeA, TypeB, TypeC, string) metodą, kuris suteiks jums kolekcijos Add(TypeA, TypeB, TypeC, string) sintaksę, pavyzdžiui:

     new MultiKeyDictionary<TypeA, TypeB, TypeC, string> { { a, b, c, null }, ... }; 
14 янв. atsakymas pateikiamas nawfal 14 jan. 2014-01-14 12:56 '14 at 12:56 2014-01-14 12:56

Jei dėl kokių nors priežasčių tikrai nenorite sukurti savo „Tuple“ klasės arba naudoti integruotą .NET 4.0, galima taikyti kitą metodą; Galite sujungti tris pagrindines vertybes į vieną vertę.

Pvz., Jei trys vertybės yra sveikojo skaičiaus rūšys, kurios nepriima daugiau nei 64 bitų, galite jas sujungti į ulong .

Blogiausiu atveju visada galite naudoti eilutę, jei įsitikinate, kad trys jo komponentai yra apriboti tam tikru simboliu ar seka, kuri nėra nustatyta pagrindiniuose komponentuose, pvz., Su trimis numeriais, kuriuos galėtumėte naudoti, pabandykite:

 string.Format("{0}#{1}#{2}", key1, key2, key3) 

Akivaizdu, kad šiuo požiūriu yra keletas pridėtinių verčių, tačiau, priklausomai nuo to, ką naudojate šiam tikslui, gali būti nepakankamai trikdyti.

6
05 июня '09 в 17:16 2009-06-05 17:16 atsakymas duotas jerryjvl birželio 05 '09, 17:16 2009-06-05 17:16

Geras, švarus, greitas, paprastas ir aiškus būdas:

tiesiog sukurkite paprastą raktų klasę, gautą iš paketo .

pridėkite kažką panašaus į:

 public sealed class myKey : Tuple<TypeA, TypeB, TypeC> { public myKey(TypeA dataA, TypeB dataB, TypeC dataC) : base (dataA, dataB, dataC) { } public TypeA DataA { get { return Item1; } } public TypeB DataB { get { return Item2; } } public TypeC DataC { get { return Item3; } } } 

Taigi galite naudoti jį su žodynu:

 var myDictinaryData = new Dictionary<myKey, string>() { {new myKey(1, 2, 3), "data123"}, {new myKey(4, 5, 6), "data456"}, {new myKey(7, 8, 9), "data789"} }; 
  • Taip pat galite ją naudoti sutartyse.
  • kaip raktas derinant arba grupuojant linq
  • Tokiu būdu jūs niekada nesuprantate dalykų 1, 2, 3 ir 3 punktų.
  • Jums nereikia prisiminti ar pažvelgti į kodą, kad išsiaiškintumėte, kur eiti, norint gauti kažką.
  • nereikia iš naujo apibrėžti IStructuralEquatable, IStructuralComparable, IComparable, ITuple, jie visi yra čia.
4
01 июня '16 в 17:59 2016-06-01 17:59 atsakymą pateikė gabba birželio 16 d. 16, 17:59 2016-06-01 17:59

Norėčiau iš naujo įkelti jūsų Tuple su tinkamu GetHashCode ir tiesiog naudoti jį kaip raktą.

Nors perkraunate tinkamus metodus, turėtumėte pamatyti tinkamus rezultatus.

4
05 июня '09 в 16:58 2009-06-05 16:58 Atsakymą pateikė John Gietzen birželio 05 '09, 16:58 2009-06-05 16:58

Čia yra .NET paketas, skirtas nuorodoms:

 [Serializable] public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple { private readonly T1 m_Item1; private readonly T2 m_Item2; private readonly T3 m_Item3; public T1 Item1 { get { return m_Item1; } } public T2 Item2 { get { return m_Item2; } } public T3 Item3 { get { return m_Item3; } } public Tuple(T1 item1, T2 item2, T3 item3) { m_Item1 = item1; m_Item2 = item2; m_Item3 = item3; } public override Boolean Equals(Object obj) { return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);; } Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) { if (other == null) return false; Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>; if (objTuple == null) { return false; } return comparer.Equals(m_Item1, objTuple.m_Item1)  comparer.Equals(m_Item2, objTuple.m_Item2)  comparer.Equals(m_Item3, objTuple.m_Item3); } Int32 IComparable.CompareTo(Object obj) { return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default); } Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) { if (other == null) return 1; Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>; if (objTuple == null) { throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other"); } int c = 0; c = comparer.Compare(m_Item1, objTuple.m_Item1); if (c != 0) return c; c = comparer.Compare(m_Item2, objTuple.m_Item2); if (c != 0) return c; return comparer.Compare(m_Item3, objTuple.m_Item3); } public override int GetHashCode() { return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default); } Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3)); } Int32 ITuple.GetHashCode(IEqualityComparer comparer) { return ((IStructuralEquatable) this).GetHashCode(comparer); } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("("); return ((ITuple)this).ToString(sb); } string ITuple.ToString(StringBuilder sb) { sb.Append(m_Item1); sb.Append(", "); sb.Append(m_Item2); sb.Append(", "); sb.Append(m_Item3); sb.Append(")"); return sb.ToString(); } int ITuple.Size { get { return 3; } } } 
3
09 июня '12 в 11:54 2012-06-09 11:54 atsakymą pateikė Michael Graczyk birželio 12 d. 12 val. 11:54 2012-06-09 11:54

Jei jūsų vartotojo kodas galėtų dirbti su IDictionary <>, o ne žodynu, mano instinktas būtų naudoti SortedDictionary <> naudojant specialų masyvo kartografavimą, ty:

 class ArrayComparer<T> : IComparer<IList<T>> where T : IComparable<T> { public int Compare(IList<T> x, IList<T> y) { int compare = 0; for (int n = 0; n < x.Count  n < y.Count; ++n) { compare = x[n].CompareTo(y[n]); } return compare; } } 

Ir sukurkite tokiu būdu (naudodami int [] tik konkrečiam pavyzdžiui):

 var dictionary = new SortedDictionary<int[], string>(new ArrayComparer<int>()); 
2
21 июня '13 в 14:32 2013-06-21 14:32 atsakymą pateikė „ mungflesh“ birželio 21 d. , 13:32, 2013-06-21 14:32

Kiti klausimai apie žymes, kurios gali būti arba Užduoti klausimą