get original key object from dictionary

Discussion in 'Microsoft C# .NET' started by not_a_commie, Dec 14, 2007.

  1. not_a_commie

    not_a_commie Guest

    given a Dictionary<object, object> and an object that exactly
    replicates the Equals and GetHashCode of the original object used as
    the dictionary key, how do I retrieve the original key that was used?
     
    not_a_commie, Dec 14, 2007
    #1
    1. Advertisements

  2. not_a_commie

    Marc Gravell Guest

    I can't see an easy way - perhaps you have to drop down to looping?
    Shown in the general (TKey / TValue) terms:

    TKey testKey; // our equivalent but different key

    IEqualityComparer<TKey> comparer = dict.Comparer;
    foreach (KeyValuePair<TKey, TValue> pair in dict) {
    if (comparer.Equals(testKey, pair.Key)) {
    return pair.Key; // the original (or a clone if
    blittable)
    }
    }
    throw new KeyNotFoundException();

    Marc
     
    Marc Gravell, Dec 14, 2007
    #2
    1. Advertisements

  3. Not sure I understand the objective here. If you used the ContainsKey method
    and it returns true, you know you have it, correct?
    -- Peter
    Site: http://www.eggheadcafe.com
    UnBlog: http://petesbloggerama.blogspot.com
    MetaFinder: http://www.blogmetafinder.com


    "not_a_commie" wrote:

    > given a Dictionary<object, object> and an object that exactly
    > replicates the Equals and GetHashCode of the original object used as
    > the dictionary key, how do I retrieve the original key that was used?
    >
     
    Peter Bromberg [C# MVP], Dec 14, 2007
    #3
  4. not_a_commie

    Marc Gravell Guest

    > Not sure I understand the objective here. If you used the ContainsKey method
    > and it returns true, you know you have it, correct?


    I believe the OP means that he has two different objects (presumably
    classes) that he considers equal - i.e. they represent the same
    Customer, but are different instances. He intends to use the one he
    has "in hand" to find the original that was used as the key in the
    dictionary. Quite common when dealing with facades, flyweights, etc.

    I have seen this done before, but I think I've concluded over the
    years that I prefer to use primatives for keys...

    Marc
     
    Marc Gravell, Dec 14, 2007
    #4
  5. not_a_commie

    Peter Duniho Guest

    On Fri, 14 Dec 2007 14:16:42 -0800, Marc Gravell <>
    wrote:

    >> Not sure I understand the objective here. If you used the ContainsKey
    >> method
    >> and it returns true, you know you have it, correct?

    >
    > I believe the OP means that he has two different objects (presumably
    > classes) that he considers equal - i.e. they represent the same
    > Customer, but are different instances. He intends to use the one he
    > has "in hand" to find the original that was used as the key in the
    > dictionary. Quite common when dealing with facades, flyweights, etc.


    But doesn't Dictionary<> already handle that correctly?

    Obviously for value types as keys, it does. But AFAIK it also does as
    well for reference types. For example, if the key is a string, as long as
    I have a string instance that is equal to the one used for the key, it
    does not have to be the same string instance as that originally used as
    the key.

    What's in the class shouldn't matter, as long as it hashes and compares
    the same as the original key.

    I share Peter B.'s confusion over the question. Seems like given what the
    OP's already stated, the Dictionary<> does just what he'd want, without
    additional work. Either he's missing something, or Peter and I are.

    Pete
     
    Peter Duniho, Dec 14, 2007
    #5
  6. I think that the OP has an instance of a type which has other members
    which don't necessarily contribute to the identity of the object being used
    as a key, and he needs to retrieve those from the original key.

    Which I agree really doesn't make sense, because if it is that
    important, those attributes should be stored elsewhere, based on the same
    key.

    --
    - Nicholas Paldino [.NET/C# MVP]
    -

    "Peter Duniho" <> wrote in message
    news:blush:...
    > On Fri, 14 Dec 2007 14:16:42 -0800, Marc Gravell <>
    > wrote:
    >
    >>> Not sure I understand the objective here. If you used the ContainsKey
    >>> method
    >>> and it returns true, you know you have it, correct?

    >>
    >> I believe the OP means that he has two different objects (presumably
    >> classes) that he considers equal - i.e. they represent the same
    >> Customer, but are different instances. He intends to use the one he
    >> has "in hand" to find the original that was used as the key in the
    >> dictionary. Quite common when dealing with facades, flyweights, etc.

    >
    > But doesn't Dictionary<> already handle that correctly?
    >
    > Obviously for value types as keys, it does. But AFAIK it also does as
    > well for reference types. For example, if the key is a string, as long as
    > I have a string instance that is equal to the one used for the key, it
    > does not have to be the same string instance as that originally used as
    > the key.
    >
    > What's in the class shouldn't matter, as long as it hashes and compares
    > the same as the original key.
    >
    > I share Peter B.'s confusion over the question. Seems like given what the
    > OP's already stated, the Dictionary<> does just what he'd want, without
    > additional work. Either he's missing something, or Peter and I are.
    >
    > Pete
     
    Nicholas Paldino [.NET/C# MVP], Dec 14, 2007
    #6
  7. not_a_commie

    Marc Gravell Guest

    > I share Peter B.'s confusion over the question. Seems like given what the
    > OP's already stated, the Dictionary<> does just what he'd want, without
    > additional work. Either he's missing something, or Peter and I are.


    The original question was (my emph): "how do I retrieve the original
    ****key**** that was used?"

    Using an alternative but equivalent *key* will allow you to get the
    same *value*, but it won't (unless I'm being really slow) allow you
    direct access to the original *key*.

    My interpretation of the question, therefore, is: in the following,
    and given you know only "dict" and "equivalentKey", obtain the
    instance "originalKey".
    The loop I provided whould do this.

    Dictionary dict = ...
    MyKey originalKey = ...
    MyValue value = ...

    dict.Add(originalKey, value);
    MyKey equivalentKey = originalKey.Clone();
     
    Marc Gravell, Dec 14, 2007
    #7
  8. not_a_commie

    Peter Duniho Guest

    On Fri, 14 Dec 2007 14:16:42 -0800, Marc Gravell <>
    wrote:

    >> Not sure I understand the objective here. If you used the ContainsKey
    >> method
    >> and it returns true, you know you have it, correct?

    >
    > I believe the OP means that he has two different objects (presumably
    > classes) that he considers equal - i.e. they represent the same
    > Customer, but are different instances.


    For the record, I wrote a small sample program (see below) that confirms
    to the OP requirements as I understand them, and without anything extra it
    "just works". I don't even have to use the same type or even a related
    type when calling ContainsKey() as that used for the actual key.

    I think some clarification is in order, if there's something OP is trying
    to do but can't.

    Pete


    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace TestCustomHashDictionary
    {
    class Program
    {
    class TestClassOne
    {
    private string _str1;
    private string _str2;

    public TestClassOne(string str1, string str2)
    {
    _str1 = str1;
    _str2 = str2;
    }

    public override int GetHashCode()
    {
    return _str1.GetHashCode() ^ _str2.GetHashCode();
    }

    public override bool Equals(object obj)
    {
    if (obj != null)
    {
    return ToString().Equals(obj.ToString());
    }

    return false;
    }

    public override string ToString()
    {
    return _str1 + _str2;
    }
    }

    class TestClassTwo
    {
    private string _str;
    private int _hash;

    public TestClassTwo(string str1, string str2)
    {
    _hash = str1.GetHashCode() ^ str2.GetHashCode();
    _str = str1 + str2;
    }

    public override int GetHashCode()
    {
    return _hash;
    }

    public override bool Equals(object obj)
    {
    return ToString().Equals(obj.ToString());
    }

    public override string ToString()
    {
    return _str;
    }
    }

    static void Main(string[] args)
    {
    Dictionary<object, object> dict = new Dictionary<object,
    object>();

    dict.Add(new TestClassOne("one", "two"), null);

    Console.WriteLine(
    "dict.ContainsKey(new TestClassTwo(\"one\", \"two\"): "
    + dict.ContainsKey(new TestClassTwo("one", "two")));

    Console.ReadLine();
    }
    }
    }
     
    Peter Duniho, Dec 14, 2007
    #8
  9. not_a_commie

    Peter Duniho Guest

    On Fri, 14 Dec 2007 15:10:01 -0800, Marc Gravell <>
    wrote:

    > The original question was (my emph): "how do I retrieve the original
    > ****key**** that was used?"
    >
    > Using an alternative but equivalent *key* will allow you to get the
    > same *value*, but it won't (unless I'm being really slow) allow you
    > direct access to the original *key*.


    No, I think I was being slow. I didn't pick up the fact that he wanted
    the original key.

    While I agree with Nicholas that this may indicate a problem with the
    basic design of the OP's code, it does highlight something that's bugged
    me about the Dictionary<> and similar classes. That is, you can get a
    collection of keys that is ordered (even if the order isn't well-defined),
    and you can check for containment of a key, but you cannot get the ordinal
    index of that key related to the collection, given the key.

    Obviously the class itself has a fast way to do that, but it doesn't
    expose it in any way as far as I know. I've seen at least two different
    situations now where it'd be useful (this scenario, and a previous thread
    that involved the fastest way to get an item from a Dictionary).

    Anyway, thanks for the clarification. I understand the OP now (and the
    misunderstanding was all mine...rereading the post, it seems fine :) ).

    Pete
     
    Peter Duniho, Dec 14, 2007
    #9
  10. not_a_commie

    Marc Gravell Guest

    > ... something that's bugged me about the Dictionary<> and similar classes
    > ... but you cannot get the ordinal index of that key related to the collection, given the key.


    Well, you can for SortedList, but that's about it... ;-(

    Marc
     
    Marc Gravell, Dec 14, 2007
    #10
  11. not_a_commie

    Peter Duniho Guest

    On Fri, 14 Dec 2007 15:40:57 -0800, Marc Gravell <>
    wrote:

    >> ... something that's bugged me about the Dictionary<> and similar
    >> classes
    >> ... but you cannot get the ordinal index of that key related to the
    >> collection, given the key.

    >
    > Well, you can for SortedList, but that's about it... ;-(


    Yes, but why only that one?

    For SortedDictionary, I understand. The underlying implementation is a
    binary tree, not an array. But the docs say that Dictionary has the same
    basic behavior as SortedList (that is, the Keys collection is a wrapper
    around the original data).

    Not all of the collection classes would lend themselves to having an
    IndexOfKey() method, but I'm not really clear on why it's not on every
    class where it apparently would make sense.

    Pete
     
    Peter Duniho, Dec 14, 2007
    #11
  12. not_a_commie

    not_a_commie Guest

    Yes, I suppose that looping is the only way to do it. Thanks for all
    your comments. I have some objects that use Guids for their uniqueId,
    their hashcode, and their equals. It's easy to make a stubbed instance
    of the class and use that as a lookup for a value if all you have is a
    Guid. Then you just keep a static reference to it and change the Guid
    on it when you need to do a lookup by Guid. However, it didn't work
    cleaning for looking up the original keys.
     
    not_a_commie, Dec 15, 2007
    #12
  13. not_a_commie

    Peter Duniho Guest

    On Fri, 14 Dec 2007 19:51:15 -0800, not_a_commie <>
    wrote:

    > Yes, I suppose that looping is the only way to do it. Thanks for all
    > your comments. I have some objects that use Guids for their uniqueId,
    > their hashcode, and their equals. It's easy to make a stubbed instance
    > of the class and use that as a lookup for a value if all you have is a
    > Guid. Then you just keep a static reference to it and change the Guid
    > on it when you need to do a lookup by Guid. However, it didn't work
    > cleaning for looking up the original keys.


    Well, maybe you could be more specific about why you need to retrieve the
    key at all.

    I'm not saying there's never a reason to, but it's not a common request.
    Usually, if you're trying to use a key/value data structure (like the
    Dictionary<> class) to look things up, you get the data you want from the
    value.

    You could just make the key the GUID and put the instances as the values.
    Or you could make the instances the key and value. Or, if you already
    have some value _and_ you still want to be able to quickly get the object
    according to the key, you could store a struct as the value in the
    dictionary that has both the GUID-based instance, as well as the value
    you're currently storing in the dictionary.

    In other words, while enumerating each and every key would certainly work,
    it kind of defeats the purpose (I think) of using a dictionary. I think
    it would make more sense to accommodate the normal usage patterns of the
    dictionary, rather than shoe-horn some alternative usage into it.

    Pete
     
    Peter Duniho, Dec 15, 2007
    #13
  14. not_a_commie wrote:
    > given a Dictionary<object, object> and an object that exactly
    > replicates the Equals and GetHashCode of the original object used as
    > the dictionary key, how do I retrieve the original key that was used?


    One solution that would introduce some overhead could be to just have
    two dictionaries, one with the key->key mapping and one with the
    key->value mapping.

    Another solution could be to create a simple struct that holds both the
    key and value, and store this in the dictionary instead of just the
    value, that way you will always have access to the original key directly.

    ie.

    (note, untested code, just written in the newsreader)

    public struct DictionaryKeyValueWrapper<TKey,TValue>
    {
    public TKey OriginalKey;
    public TValue Value;
    public DictionaryKeyValueWrapper(TKey originalKey, TValue value)
    {
    OriginalKey = originalKey;
    Value = value;
    }
    public DictionaryKeyValueWrapper()
    {
    OriginalKey = default(TKey);
    Value = default(TValue);
    }
    }

    then you could do:

    dict[key_lookalike].OriginalKey
    dict[key_lookalike].Value

    --
    Lasse Vågsæther Karlsen
    mailto:
    http://presentationmode.blogspot.com/
     
    Lasse Vågsæther Karlsen, Dec 15, 2007
    #14
  15. not_a_commie

    not_a_commie Guest

    So I ended up with a dictionary where the key is the Guid and the
    value is a KeyValuePair of the two objects I need indexed by that Guid.
     
    not_a_commie, Dec 15, 2007
    #15
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lex Yacc
    Replies:
    0
    Views:
    274
    Lex Yacc
    Aug 7, 2003
  2. smith
    Replies:
    3
    Views:
    163
    Jon Skeet [C# MVP]
    Nov 26, 2003
  3. Luigi

    Get Dictionary key by value

    Luigi, Sep 22, 2008, in forum: Microsoft C# .NET
    Replies:
    11
    Views:
    9,239
    Ali Imam
    Nov 25, 2010
  4. Luigi

    Dictionary with object for key

    Luigi, Nov 4, 2008, in forum: Microsoft C# .NET
    Replies:
    2
    Views:
    223
    Arne Vajhøj
    Nov 4, 2008
  5. Luigi

    Get the key type of a Dictionary

    Luigi, Nov 26, 2008, in forum: Microsoft C# .NET
    Replies:
    4
    Views:
    1,020
    Jeroen Mostert
    Nov 26, 2008
Loading...

Share This Page