278. Double keyed Dictionary

לפעמים אנחנו מעוניינים בDictionary שמבוסס יותר ממפתח אחד,

למה הכוונה?

אנחנו רגילים לDictionary עם מפתח אחד, זה בד”כ מיפוי בין איזשהו מפתח (חד חד ערכי) לערך אחר.

למשל, נניח מיפוי בין תעודת זהות של אדם, לשם שלו.

אבל ניתן להרחיב את הקונספט לDictionary מבוסס מספר מפתחות,

למשל, המושג של מספר תעודת זהות הוא באמת חד חד ערכי, אבל רק בהקשר של מדינה מסוימת.

לכן היינו רוצים לייצג איזשהו מיפוי מסוים בין מדינות ותעודות זהות, לשמות של אנשים.

הדרך הפשוטה ביותר ליצור מימוש כזה היא ע”י שימוש באיזושהי מחלקה המייצגת זוג, למשל KeyValuePair, או Tuple (אם יש לכם יותר מזל ואתם מתכנתים בFramework 4.0, ראו גם טיפים 17, 126)

זה נראה ככה בערך:

1
2
3
4
5
6
Dictionary<Tuple<string, int>, string> stateAndIdToName =
new Dictionary<Tuple<string, int>, string>()
{
{Tuple.Create("Israel", 314159260), "Haim Pi"},
{Tuple.Create("Egypt", 314159260), "Achmad Pi"},
};

(ראו גם טיפ מספר 18, 126)

וגישה לDictionary מתבצעת כך:

1
2
string israeliPiMinister =
stateAndIdToName[Tuple.Create("Israel", 314159260)];

ניתן גם לרשת מDictionary כדי להוסיף Overloadים נוחים:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class DoubleKeyDictionary<TKey1, TKey2, TValue> :
Dictionary<Tuple<TKey1, TKey2>, TValue>
{
public void Add(TKey1 key1, TKey2 key2, TValue value)
{
this.Add(Tuple.Create(key1, key2), value);
}
public TValue this[TKey1 key1, TKey2 key2]
{
get
{
return this[Tuple.Create(key1, key2)];
}
set
{
this[Tuple.Create(key1, key2)] = value;
}
}
public bool ContainsKey(TKey1 key1, TKey2 key2)
{
return this.ContainsKey(Tuple.Create(key1, key2));
}
public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue result)
{
return this.TryGetValue(Tuple.Create(key1, key2), out result);
}
}

שימו לב שהירושה נותנת לנו בעיקר שלושה דברים:

  • את האפשרות להגדיר את הDictionary בצורה יותר נוחה: DoubleKeyDictionary<string, int, string> במקום Dictionary<Tuple<string, int>, string>
  • את הIndexer הנוח המאפשר לנו לכתוב כך:

    1
    2
    string israeliPiMinister = stateAndIdToName["Israel", 314159260];
    stateAndIdToName["Israel", 314159260] = "Haim Pi";
  • את פונקציית הAdd, המאפשרת לנו להגדיר את הDictionary בצורה יותר נוחה (ראו גם טיפ מספר 18):

    1
    2
    3
    4
    5
    6
    DoubleKeyDictionary<string, int, string> stateAndIdToName =
    new DoubleKeyDictionary<string, int, string>()
    {
    {"Israel", 314159260, "Haim Pi"},
    {"Egypt", 314159260, "Achmad Pi"},
    };

בשביל שתי המתודות הנוספות, אפשר גם לא לרשת, ולהפוך אותן לExtension Methods של IDictionary<Tuple<TKey1, TKey2>, TValue>. החל מC# 6.0 אפשר גם להפוך את Add לExtension Method מתאים בשביל לקבל את הסינטקס הנ"ל.

המשך יום פעמיים כי טוב

שתף