Dictionary bidirectional

Discussion in 'Python' started by Kless, Jul 14, 2008.

  1. Kless

    Kless Guest

    I need a dictionary where get the result from a 'key' (on left), but
    also from a 'value' (on right), how to get it?

    I know that dictionaries aren't bidirectional, but is there any way
    without use two dictionaries?


    Thanks in advance!
     
    Kless, Jul 14, 2008
    #1
    1. Advertising

  2. Kless

    WDC Guest

    On Jul 13, 4:21 pm, Kless <> wrote:
    > I need a dictionary where get the result from a 'key' (on left), but
    > also from a 'value' (on right), how to get it?
    >
    > I know that dictionaries aren't bidirectional, but is there any way
    > without use two dictionaries?
    >
    > Thanks in advance!


    You want to print the key as well as the value?
     
    WDC, Jul 14, 2008
    #2
    1. Advertising

  3. Kless

    bukzor Guest

    On Jul 13, 4:21 pm, Kless <> wrote:
    > I need a dictionary where get the result from a 'key' (on left), but
    > also from a 'value' (on right), how to get it?
    >
    > I know that dictionaries aren't bidirectional, but is there any way
    > without use two dictionaries?
    >
    > Thanks in advance!


    You need to use two dictionaries. Here's a class that someone's
    written that wraps it up into a single dict-like object for you:

    http://www.faqts.com/knowledge_base/view.phtml/aid/4376
     
    bukzor, Jul 14, 2008
    #3
  4. Kless

    Guest

    bukzor:
    > You need to use two dictionaries. Here's a class that someone's
    > written that wraps it up into a single dict-like object for you:
    > http://www.faqts.com/knowledge_base/view.phtml/aid/4376


    It contains code like:

    try:
    del self.data[item]
    except KeyError:
    pass

    Exceptions are useful in python, but with dictionaries this is
    probably faster (and shorter), even if it may perform two lookups:

    if item in self.data:
    del self.data[item]

    Bye,
    bearophile
     
    , Jul 14, 2008
    #4
  5. Kless

    bukzor Guest

    On Jul 13, 6:53 pm, Larry Bates <`> wrote:
    > wrote:
    > > bukzor:
    > >> You need to use two dictionaries. Here's a class that someone's
    > >> written that wraps it up into a single dict-like object for you:
    > >>http://www.faqts.com/knowledge_base/view.phtml/aid/4376

    >
    > > It contains code like:

    >
    > > try:
    > > del self.data[item]
    > > except KeyError:
    > > pass

    >
    > > Exceptions are useful in python, but with dictionaries this is
    > > probably faster (and shorter), even if it may perform two lookups:

    >
    > > if item in self.data:
    > > del self.data[item]

    >
    > > Bye,
    > > bearophile

    >
    > The only case where it would be faster would be if most of the keys were NOT in
    > the dictionary (rather odd use case). Otherwise I believe you will find the
    > first way quicker as the exceptions are infrequent.
    >
    > -Larry


    /agree
     
    bukzor, Jul 14, 2008
    #5
  6. Kless

    Kless Guest

    But in my dictionary both keys and values are unique.

    On Jul 14, 7:34 am, Dennis Lee Bieber <> wrote:
    > On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
    > <> declaimed the following in comp.lang.python:
    >
    > > I need a dictionary where get the result from a 'key' (on left), but
    > > also from a 'value' (on right), how to get it?

    >
    > > I know that dictionaries aren't bidirectional, but is there any way
    > > without use two dictionaries?

    >
    >         Just out of curiosity... What do you expect to have returned from...
    >
    > aDict = { "one" : "two",
    >                 "three" : "four",
    >                 "What?" : "two"     }
    >
    > when looking for the value "two"?
    >
    >         In a dictionary, the /keys/ are unique... but the /values/ can be
    > duplicates.
     
    Kless, Jul 14, 2008
    #6
  7. Kless

    Ken Starks Guest

    Dennis Lee Bieber wrote:
    > On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
    > <> declaimed the following in comp.lang.python:
    >
    >> I need a dictionary where get the result from a 'key' (on left), but
    >> also from a 'value' (on right), how to get it?
    >>
    >> I know that dictionaries aren't bidirectional, but is there any way
    >> without use two dictionaries?
    >>

    > Just out of curiosity... What do you expect to have returned from...
    >
    > aDict = { "one" : "two",
    > "three" : "four",
    > "What?" : "two" }
    >
    > when looking for the value "two"?
    >
    > In a dictionary, the /keys/ are unique... but the /values/ can be
    > duplicates.


    I wonder if anyone has implemented an 'equivalence class' class (for
    finite sets) based on this.

    Obviously the relation defined by
    k1~k2 iff D[k1] == D[k2]
    does partition the set of all keys as an equivalence class.

    So ... as a kind of inverse you could return a set, a subset of the
    keys. How you would get a canonical representative of that set is
    a different matter, of course. Unless, as in the OP's case, it is
    a singleton set.

    It would seem more efficient to do this when a key-value pair is
    added or removed from the original dictionary rather than iterating
    over all the keys each time you used it.
     
    Ken Starks, Jul 14, 2008
    #7
  8. Kless

    Guest

    Larry Bates:
    > The only case where it would be faster would be if most of the keys were NOT in
    > the dictionary (rather odd use case). Otherwise I believe you will find the
    > first way quicker as the exceptions are infrequent.


    I have written a small benchmark:

    from random import shuffle

    def test1(data, to_delete):
    for item in to_delete:
    try:
    del data[item]
    except KeyError:
    pass

    def test2(data, to_delete):
    for item in to_delete:
    if item in data:
    del data[item]

    N = 1000000
    M = 2 * N

    data = dict.fromkeys(xrange(N), 0)
    to_delete = range(M)
    shuffle(to_delete)

    from timeit import default_timer as clock
    t = clock()
    #test1(data, to_delete) # 2.4 s
    test2(data, to_delete) # 0.8 s
    print round(clock() - t, 2), "s"

    It creates a dictionary of the first million integers, and then tries
    to delete the first two million of integers. So about 1/2 numbers are
    present to be deleted. In this situation the version with the try-
    except seems about 3 times slower than the other.

    Bye,
    bearophile
     
    , Jul 14, 2008
    #8
  9. Kless

    Kless Guest

    Akathorn Greyhat sent me by email the next solution, which althought
    isn't generic it works well:

    -------------
    You could make your own class for that, maybe something like


    #########

    class MyCoolDictionary(dict):
    def __init__(self, *args, **kargs):
    dict.__init__(self, *args, **kargs)

    def __getitem__(self, item):
    try:
    return dict.__getitem__(self, item)

    except KeyError:
    keys=[]
    for i in dictio.keys():
    if dictio==item:
    keys.append(i)
    return keys

    dictio=MyCoolDictionary({"a" : 1, "b" : 2, "c" : 2})
    print dictio["a"]
    print dictio["b"]
    print dictio[1]
    print dictio[2]
    #########

    The output of this code is:
    1
    2
    ['a']
    ['c', 'b']

    Note that it isn't finish, maybe you'll need to make some kind of test
    before adding a new value because with this code one value can have
    multiple keys, and I have fixed it by returning a list of keys instead
    a single value. It's up to you =)

    I'm sorry of my poor english =(

    Regards,
    Akathorn Greyhat
    -------------
     
    Kless, Jul 14, 2008
    #9
  10. If keys and values are unique you could do this...

    --------------

    # Left : Right
    roman = { "One" : "I",
    "Two" : "II",
    "Three" : "III",
    "Four" : "IV",
    "Five" : "V",
    "Six" : "VI",
    "Seven" : "VII",
    "Eight" : "VIII",
    "Nine" : "IX",
    "Ten" : "X" }

    left, right = zip( *roman.items() )
    left = list(left)
    right = list(right)

    print left[ right.index("VIII") ]

    --------------

    .... result is "Eight".

    Hmmm! zip returns tuples, which need to be turned into lists to do
    much with. Maybe not the best solution in this case.

    Verse.
     
    Impotent Verse, Jul 14, 2008
    #10
  11. Kless

    Gerry Guest

    If keys and values are unique, maybe just store both in the same
    dictionary:

    mydict[a] = b
    mydict = a

    ...

    Gerry

    On Jul 14, 8:31 am, Impotent Verse <> wrote:
    > If keys and values are unique you could do this...
    >
    > --------------
    >
    > #         Left      : Right
    > roman = { "One"     : "I",
    >           "Two"     : "II",
    >           "Three"   : "III",
    >           "Four"    : "IV",
    >           "Five"    : "V",
    >           "Six"     : "VI",
    >           "Seven"   : "VII",
    >           "Eight"   : "VIII",
    >           "Nine"    : "IX",
    >           "Ten"     : "X" }
    >
    > left, right = zip( *roman.items() )
    > left = list(left)
    > right = list(right)
    >
    > print left[ right.index("VIII") ]
    >
    > --------------
    >
    > ... result is "Eight".
    >
    > Hmmm! zip returns tuples, which need to be turned into lists to do
    > much with. Maybe not the best solution in this case.
    >
    > Verse.
     
    Gerry, Jul 14, 2008
    #11
    1. Advertising

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. Ilias Lazaridis
    Replies:
    6
    Views:
    483
    Ilias Lazaridis
    Feb 21, 2006
  2. Manfred Balik
    Replies:
    12
    Views:
    6,722
    Marc Guardiani
    Sep 10, 2006
  3. james_027
    Replies:
    1
    Views:
    362
    Marc 'BlackJack' Rintsch
    Aug 22, 2007
  4. Navkirat Singh
    Replies:
    6
    Views:
    3,331
    Navkirat Singh
    Jul 29, 2010
  5. Chris Rebert
    Replies:
    0
    Views:
    573
    Chris Rebert
    Jul 29, 2010
Loading...

Share This Page