Dictionary bidirectional

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kless

    Dictionary bidirectional

    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!
  • WDC

    #2
    Re: Dictionary bidirectional

    On Jul 13, 4:21 pm, Kless <jonas....@goog lemail.comwrote :
    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?

    Comment

    • bukzor

      #3
      Re: Dictionary bidirectional

      On Jul 13, 4:21 pm, Kless <jonas....@goog lemail.comwrote :
      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:


      Comment

      • bearophileHUGS@lycos.com

        #4
        Re: Dictionary bidirectional

        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

        Comment

        • Larry Bates

          #5
          Re: Dictionary bidirectional

          bearophileHUGS@ lycos.com 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

          Comment

          • bukzor

            #6
            Re: Dictionary bidirectional

            On Jul 13, 6:53 pm, Larry Bates <larry.ba...@we bsafe.com`wrote :
            bearophileH...@ lycos.com 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

            Comment

            • Kless

              #7
              Re: Dictionary bidirectional

              But in my dictionary both keys and values are unique.

              On Jul 14, 7:34 am, Dennis Lee Bieber <wlfr...@ix.net com.comwrote:
              On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
              <jonas....@goog lemail.comdecla imed the following in comp.lang.pytho n:
              >
              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.

              Comment

              • Ken Starks

                #8
                Re: Dictionary bidirectional

                Dennis Lee Bieber wrote:
                On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
                <jonas.esp@goog lemail.comdecla imed the following in comp.lang.pytho n:
                >
                >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.


                Comment

                • bearophileHUGS@lycos.com

                  #9
                  Re: Dictionary bidirectional

                  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(x range(N), 0)
                  to_delete = range(M)
                  shuffle(to_dele te)

                  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

                  Comment

                  • Kless

                    #10
                    Re: Dictionary bidirectional

                    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 MyCoolDictionar y(dict):
                    def __init__(self, *args, **kargs):
                    dict.__init__(s elf, *args, **kargs)

                    def __getitem__(sel f, item):
                    try:
                    return dict.__getitem_ _(self, item)

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

                    dictio=MyCoolDi ctionary({"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
                    -------------

                    Comment

                    • Impotent Verse

                      #11
                      Re: Dictionary bidirectional

                      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("VI II") ]

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

                      .... 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.

                      Comment

                      • Gerry

                        #12
                        Re: Dictionary bidirectional

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

                        mydict[a] = b
                        mydict[b] = a

                        ...

                        Gerry

                        On Jul 14, 8:31 am, Impotent Verse <simon.pever... @gmail.comwrote :
                        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("VI II") ]
                        >
                        --------------
                        >
                        ... 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.

                        Comment

                        Working...