Re: Dictionary bidirectional

2008-07-14 Thread Gerry
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 <[EMAIL PROTECTED]> 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.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-14 Thread Akathorn Greyhat
This is a better version of the class that I sen't you, now it raises a
KeyError when you try to insert a value that is already in


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

def __setitem__(self, *args, **kargs):
for i in dictio.values():
if args[0]==i or args[1]==i:
raise KeyError, 'Value already exists'

dict.__setitem__(self, *args, **kargs)

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

except KeyError:
keys=[]
for i in dictio.keys():
if dictio[i]==item:
keys.append(i)
if not keys:
raise KeyError, 'Can\'t found key or value "' + str(item) +
'"'
return keys


Feel free to change anything you want or need

Regards,
Akathorn Greyhat


2008/7/14 Kless <[EMAIL PROTECTED]>:

> 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!
> --
> http://mail.python.org/mailman/listinfo/python-list
>
--
http://mail.python.org/mailman/listinfo/python-list

Re: Dictionary bidirectional

2008-07-14 Thread Impotent Verse
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.

--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-14 Thread Kless
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[i]==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
-
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-14 Thread bearophileHUGS
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 = 100
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-14 Thread Ken Starks

Dennis Lee Bieber wrote:

On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
<[EMAIL PROTECTED]> 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.


--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-14 Thread Kless
But in my dictionary both keys and values are unique.

On Jul 14, 7:34 am, Dennis Lee Bieber <[EMAIL PROTECTED]> wrote:
> On Sun, 13 Jul 2008 16:21:11 -0700 (PDT), Kless
> <[EMAIL PROTECTED]> 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.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-13 Thread bukzor
On Jul 13, 6:53 pm, Larry Bates <[EMAIL PROTECTED]> wrote:
> [EMAIL PROTECTED] 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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-13 Thread Akathorn Greyhat
-- Forwarded message --
From: Akathorn Greyhat <[EMAIL PROTECTED]>
Date: 2008/7/14
Subject: Re: Dictionary bidirectional
To: Kless <[EMAIL PROTECTED]>




2008/7/14 Kless <[EMAIL PROTECTED]>:

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!
> --
> http://mail.python.org/mailman/listinfo/python-list
>


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[i]==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
--
http://mail.python.org/mailman/listinfo/python-list

Re: Dictionary bidirectional

2008-07-13 Thread Larry Bates

[EMAIL PROTECTED] 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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-13 Thread bearophileHUGS
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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-13 Thread bukzor
On Jul 13, 4:21 pm, Kless <[EMAIL PROTECTED]> 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
--
http://mail.python.org/mailman/listinfo/python-list


Re: Dictionary bidirectional

2008-07-13 Thread WDC
On Jul 13, 4:21 pm, Kless <[EMAIL PROTECTED]> 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?
--
http://mail.python.org/mailman/listinfo/python-list


Dictionary bidirectional

2008-07-13 Thread Kless
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!
--
http://mail.python.org/mailman/listinfo/python-list