我需要一個更堅固的字典狀結構來獲得:通過提供一種鍵(默認字典行爲)IBiLookup和Bilookup:鍵和值「字典」查找
- 值;
- 鍵通過提供一個值(不那麼微不足道)。
另外,我想擴大這個字典狀結構的功能,這樣的關鍵可以用多個值關聯。
通過this討論,this答案和this other one提供了實現該工具的工具。我決定從BiDictionary中刪除「通過索引訪問」(Jon Skeet的答案),因爲模糊會比我想要的更頻繁地發生(例如,將字符串映射到字符串時)。我想出了類似字典「結構」是:
using System.Collections.Generic;
public interface IBiLookup<TLeft, TRight>
{
IDictionary<TLeft, ICollection<TRight>> LeftToRight { get; }
IDictionary<TRight, ICollection<TLeft>> RightToLeft { get; }
bool TryGetByLeft(TLeft left, out ICollection<TRight> rights);
bool TryGetByRight(TRight right, out ICollection<TLeft> lefts);
void Add(TLeft left, TRight right);
}
public class BiLookup<TLeft, TRight> : IBiLookup<TLeft, TRight>
{
public IDictionary<TLeft, ICollection<TRight>> LeftToRight
{
get { return this.leftToRight; }
}
public IDictionary<TRight, ICollection<TLeft>> RightToLeft
{
get { return this.rightToLeft; }
}
public bool TryGetByLeft(TLeft left, out ICollection<TRight> rights)
{
return LeftToRight.TryGetValue(left, out rights);
}
public bool TryGetByRight(TRight right, out ICollection<TLeft> lefts)
{
return RightToLeft.TryGetValue(right, out lefts);
}
public void Add(TLeft left, TRight right)
{
AddLeftToRight(left, right);
AddRightToLeft(right, left);
}
private void AddLeftToRight(TLeft left, TRight right)
{
ICollection<TRight> rights;
// 1) Is there an entry associated with the "left" value?
// 2) If so, is the "right" value already associated?
if (!TryGetByLeft(left, out rights))
{
// Then we have to add an entry in the leftToRight dictionary.
rights = new List<TRight> { right };
}
else
{
// So there are entries associated with the "left" value.
// We must verify if the "right" value itself is not there.
if (((List<TRight>)rights).FindIndex(element => element.Equals(right)) < 0)
{
// We don't have that association yet.
rights.Add(right);
}
else
{
// The value is already in the list: do nothing.
return;
}
}
LeftToRight[left] = rights;
}
private void AddRightToLeft(TRight right, TLeft left)
{
ICollection<TLeft> lefts;
// 1) Is there an entry associated with the "right" value?
// 2) If so, is the "left" value already associated?
if (!TryGetByRight(right, out lefts))
{
// Then we have to add an entry in the leftToRight dictionary.
lefts = new List<TLeft> { left };
}
else
{
// So there are entries associated with the "right" value.
// We must verify if the "right" value itself is not there.
if (((List<TLeft>)lefts).FindIndex(element => element.Equals(left)) < 0)
{
// We don't have that association yet.
lefts.Add(left);
}
else
{
// The value is already in the list: do nothing.
return;
}
}
RightToLeft[right] = lefts;
}
#region Fields
private IDictionary<TLeft, ICollection<TRight>> leftToRight = new Dictionary<TLeft, ICollection<TRight>>();
private IDictionary<TRight, ICollection<TLeft>> rightToLeft = new Dictionary<TRight, ICollection<TLeft>>();
#endregion
}
我很擔心,如果分割的添加(...)方法分爲二,更具體的方法,是這是一個很好的實現,因爲BiLookup類將被廣泛使用,並且需要注意性能。另外,這個線程的的目的是討論接口和類實現是否儘可能好,或者可以改進它們。
如果我將接口和「deafult」實現同時保存到類庫項目中,那麼設計是否足以重用?
如果您想討論性能,指定需求是一個好主意。它看起來像你不關心添加性能,但希望兩個查找O(1)。 – 2013-03-05 17:20:03
你是對的,但由於需求有些「鬆散」,我只想確保不會爲簡單(和過度使用)的添加(...)操作添加不必要的開銷。 – victorph 2013-03-05 17:23:05