2015-09-18 46 views
0

,你罵我之前,我知道有一個非常類似的問題:數據結構現在

Best data structure for two way mapping?

其實,我找了一個數據結構,將完成相同事情。具體來說,我有一個字符串應該被映射到另一個字符串,而另一個字符串也應該映射到原始字符串。

例如:

".jpg" -> "image/jpeg" 
"image/jpeg" -> ".jpg" 

鏈接的問題建議使用某種HashMap的或Dictionary<string,string>的做到這一點。

人們必須將持有兩個字典,每個字典是映射的一種方式自定義數據類型。這將提供O(1),但我發現它根本不可擴縮

考慮到我有一個字典從200種MIME類型相關的文件擴展名的映射,我需要建立一個類似的,具有相同的內容,但反轉。這很容易出現拼寫錯誤或丟失鍵,並且是很多重複的代碼。我想在C#尋找一個解決方案。

是否有支持這些類型的物體之間的雙向映射.NET數據結構?

如果沒有,我怎麼能做到這一點,而不復制代碼(如兩個庫解決方案)?

+0

從理論上講,你需要'dictionary.Add(「.jpg」,「image/jpg」)'',並且可以將它用作var mime = dictionary [「。jpg」]''var var ext = dictionary [ 「圖像/ JPG」]'? –

+0

@DaveZych正是! –

+0

似乎有點毫無意義,因爲你仍然可以明確映射這些關係已經.. –

回答

2

爲什麼使用兩個字典的自定義類型不起作用?雖然它會使用兩倍的內存,但它允許O(1)查找,並且應該按照您的要求工作。

然而,當涉及到通用參數,它可以變得有點毛。如果指定了相同的類型,這不是問題,但是如果指定了不同的類型,則索引器會中斷,因爲只能以單向方式獲取值。如果你重載索引,有兩個,即:

public K this[T value] 
public T this[K value] 

這將打破,如果你有相同的參數,因爲它不能夠解決。在這種情況下,我建議有兩個不同的類別:

public class TwoWayDictionary<T> 
{ 
    private Dictionary<T, T> _first; 
    private Dictionary<T, T> _second; 

    public TwoWayDictionary() 
    { 
     _first = new Dictionary<T, T>(); 
     _second = new Dictionary<T, T>(); 
    } 

    public void Add(T first, T second) 
    { 
     _first.Add(first, second); 
     _second.Add(second, first); 
    } 

    public T this[T value] 
    { 
     get 
     { 
      if(_first.ContainsKey(value)) 
      { 
       return _first[value]; 
      } 
      if(_second.ContainsKey(value)) 
      { 
       return _second[value]; 
      } 

      throw new ArgumentException(nameof(value)); 
     } 
    } 
} 

public class TwoWayDictionary<T, K> 
{ 
    private readonly Dictionary<T, K> _first; 
    private readonly Dictionary<K, T> _second; 

    public TwoWayDictionary() 
    { 
     _first = new Dictionary<T, K>(); 
     _second = new Dictionary<K, T>(); 
    } 

    public void Add(T first, K second) 
    { 
     _first.Add(first, second); 
     _second.Add(second, first); 
    } 

    public K this[T value] 
    { 
     get 
     { 
      if (_first.ContainsKey(value)) 
      { 
       return _first[value]; 
      } 

      throw new ArgumentException(nameof(value)); 
     } 
    } 

    public T this[K value] 
    { 
     get 
     { 
      if (_second.ContainsKey(value)) 
      { 
       return _second[value]; 
      } 

      throw new ArgumentException(nameof(value)); 
     } 
    } 
}  

這將允許你使用它就像在評論中提到:

var dict = new TwoWayDictionary<string>(); 
dict.Add(".jpg", "image/jpg"); 
var mime = dict[".jpg"]; 
var ext = dict["image/jpg"]; 

,並指定2如果你想不同的類型:

var dict = new TwoWayDictionary<string, int>(); 
dict.Add(".jpg", 100); 
var number = dict[".jpg"]; 
var ext = dict[100]; 
+0

我是爲了它。唯一我不喜歡的是索引器的二元性。我寧願公開兩個單獨的方法,例如'string GetFirst(string second)'和'string GetSecond(string first)' –

+0

@IvanStoev揭露兩個單獨的索引器幾乎完全打敗了類的目的。如果這樣做,你將不得不在課堂外進行包含/空的檢查。在那種情況下,爲什麼即使有班級 - 爲什麼不只是有2個字典,並檢查他們每個人的存在。 –

+0

我不這麼認爲。我看到的這個類的主要好處是**封裝**。還可以想象你引入了像TwoWayDictionary 這樣的通用參數。那麼索引器的簽名是什麼?順便說一句,我upvoted你的答案,所以我們在同一方:-) –