双向键值收集

时间:2018-09-04 08:24:02

标签: c# dictionary collections

C#中是否有一个集合像字典一样工作,并且具有多个允许双向访问的键?例如:

Collection<int, string> a = new Collection<int, string>();
a.Add(1, "a");
a.Add(1, "b");
a.Add(2, "a");
a.Get(1);//returns ["a", "b"]
a.InverseGet("a"); //returns [1, 2]

2 个答案:

答案 0 :(得分:2)

使用Tuple List<Tuple<int,string>>允许具有相同键的集合,以及LINQ对集合进行查询Where

例如,

List<Tuple<int,string>> list = new List<Tuple<int,string>>();
list.Add(Tuple.Create(23, "Foo"));
list.Add(Tuple.Create(23, "Bar"));
list.Add(Tuple.Create(25, "Bar"));

var keys = list.Where(x=> x.Item1 == 23).Select(x=> x.Item2); // FOO, BAR
var values = list.Where(x=> x.Item2 == "Bar").Select(x=> x.Item1); ; // 23, 25

答案 1 :(得分:0)

这是一个解决方案,可为您提供双向字典查找的性能。我假设您要忽略重复的元组,并且默认比较器就足够了。剩下的实现诸如删除之类的其他操作只是读者的练习

public class TwoWayCollection<A, B>
{
    private Dictionary<A, HashSet<B>> byADictionary = new Dictionary<A, HashSet<B>>();
    private Dictionary<B, HashSet<A>> byBDictionary = new Dictionary<B, HashSet<A>>();

    public IEnumerable<B> Get(A a)
    {
        return byADictionary[a];
    }

    public IEnumerable<A> InverseGet(B b)
    {
        return byBDictionary[b];
    }

    public void Add(A a, B b)
    {
        if (!byADictionary.ContainsKey(a))
        {
            byADictionary[a] = new HashSet<B>();
        }
        byADictionary[a].Add(b);
        if (!byBDictionary.ContainsKey(b))
        {
            byBDictionary[b] = new HashSet<A>();
        }
        byBDictionary[b].Add(a);
    }
}

然后使用它实际上是您建议的代码。按照字典,Get和InverseGet都接近O(1)

TwoWayCollection<int, string> a = new TwoWayCollection<int, string>();
a.Add(1, "a");
a.Add(1, "b");
a.Add(2, "a");
a.Get(1); //returns ["a", "b"]
a.InverseGet("a"); //returns [1, 2]