Two-way key value collection [duplicate]

Two-way key value collection [duplicate]



This question already has an answer here:



Is there a collection in C# working like dictionary with multiple keys allowing bidirectional access? For example:


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]



This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.





You have LINQ for that.
– SeM
Sep 4 '18 at 8:25





A simple .Where() would do the job if you don't care about performance that much
– Panagiotis Kanavos
Sep 4 '18 at 8:26


.Where()





Another option is the DataTable. It doesn't care about directions and can use indexes to improve performance
– Panagiotis Kanavos
Sep 4 '18 at 8:28






You should use a list of key value pairs. var collection = new List<KeyValuePair<int, string>>(); This you can query with LINQ easily.
– ChristianMurschall
Sep 4 '18 at 8:28


var collection = new List<KeyValuePair<int, string>>();





@Linuxrocks there's no need to use a KVP, an array of tuples will work just as well
– Panagiotis Kanavos
Sep 4 '18 at 8:29




2 Answers
2



Using Tuple List<Tuple<int,string>> to allow a collection with the same key and LINQ to make a query Where to your collection


List<Tuple<int,string>>


LINQ



For example,


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



Here is a solution that gives you the performance of a dictionary lookup in both directions. I assume that you want to ignore duplicate tuples and the default comparer is sufficient. Implementing the other operations like Remove is left as an exercise for the reader


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);




Then to use it is literally your proposed code. Both Get and InverseGet approach O(1) as per dictionary


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]

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)