1

I have a Key class contain some members. How would I filter a dictionary when I only have one member of the key object. Here is some code:

class Key
{
    public int a { get; set; }
    public int b { get; set; }
}

public class KeyEqualityComparer : IEqualityComparer<Key>
{
    public int GetHashCode(Key k)
    {
        return (k.a + k.b).GetHashCode();
    }

    public bool Equals(Key lhs, Key rhs)
    {
        return ((lhs.a == rhs.a) && (lhs.b == rhs.b));
    }
}

static Dictionary<Key, int> Data = new Dictionary<Key, int>( new KeyEqualityComparer() );

static void Main(string[] args)
{
    Data.Add(new Key() { a = 0, b = 0 }, 99);
    Data.Add(new Key() { a = 1, b = 0 }, 99);

    // select all keys value pairs where the key contains a == 0
}
chhenning
  • 2,017
  • 3
  • 26
  • 44
  • 3
    don't know if that matters in your case, but worth mantioning that `(2+3).GetHashCode()` and `(6 + (-1)).GetHashCode()`, are completely different pairs from numerical point of view, but give the same result. – Tigran Oct 24 '13 at 19:08
  • U are correct. I have not thought about that yet. Thanks for pointing out. – chhenning Oct 24 '13 at 19:12
  • Here's a good hash code formula: http://stackoverflow.com/a/892640/781792 – Tim S. Oct 24 '13 at 19:23

2 Answers2

4
var myPairs = Data.Where(pair => pair.Key.a == 0);

If you're going to be doing multiple lookups by the same propert(ies) of the Key, you can use ToLookup to make this more efficient:

var myLookup = Data.ToLookup(pair => pair.Key.a);
var myPairs = myLookup[0];
Tim S.
  • 55,448
  • 7
  • 96
  • 122
  • Doing it this way defeats the purpose of the dictionary – Matthew Oct 24 '13 at 19:10
  • If you want it another way, you have to rehash the dictionary. If you know that looking up by `a` will be a common thing, you can make another dictionary, maybe of type `Dictionary>>`. You could even make a class that exposes lookups by `Key`, `a`, and `b` and keeps add/removes synchronized if such a thing were useful. But just for the what the question asked, I figured this was fine. – Tim S. Oct 24 '13 at 19:12
  • There's also `ToLookup`, which I've now added to my answer. – Tim S. Oct 24 '13 at 19:15
  • +1 `ToLookup` is a good solution if you intend to do this more than once. – Matthew Oct 24 '13 at 19:16
1

Searching for a part of a composite key in the dictionary which doesn't use that value in its IEqualityComparer defeats the point of the dictionary. You might as well use a List.

I suggest you modify your KeyEqualityComparer to behave different when parts of the composite key are not provided.

Alternatively, if you intend to do many lookups this way and infrequent writes you may maintain multiple dictionaries having different equality comparers.

Matthew
  • 10,244
  • 5
  • 49
  • 104