By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,034 Members | 1,012 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,034 IT Pros & Developers. It's quick & easy.

Order of elements in a dict

P: n/a
Hi!

In dictionaries, unlinke lists, it doesn't matter the order one inserts
the contents, elements are stored using its own rules.

Ex:
d = {3: 4, 1: 2}
d {1: 2, 3: 4}

So, my question is: if I use keys() and values() it will give me the
keys and values in the same order?

In other words, it is safe to do:
dd = dict(zip(d.values(),d.keys()))
to exchange keys and values on a dictionary? Or I can have the values
and keys in a different order and end with something like this:
dd {2: 3 , 4: 1}

instead of:
dd

{2: 1, 4: 3}

For this example it works as I wanted (the second output), but can I
trust this?

Also, if someone has a better way to exchange keys and values in a dict,
I would like to learn. :-)

Thanks!

Marcio
Jul 19 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Marcio Rosa da Silva wrote:
In other words, it is safe to do:
>>> dd = dict(zip(d.values(),d.keys()))


Yes, if the dictionary isn't modified between the invocation of values() and
keys(). Quoting http://docs.python.org/lib/typesmapping.html

"""
Keys and values are listed in an arbitrary order which is non-random, varies
across Python implementations, and depends on the dictionary's history of
insertions and deletions. If items(), keys(), values(), iteritems(),
iterkeys(), and itervalues() are called with no intervening modifications
to the dictionary, the lists will directly correspond. This allows the
creation of (value, key) pairs using zip(): "pairs = zip(a.values(),
a.keys())". The same relationship holds for the iterkeys() and itervalues()
methods: "pairs = zip(a.itervalues(), a.iterkeys())" provides the same
value for
"""

I suppose you are aware that you lose information if multiple keys have the
same value.

Peter
Jul 19 '05 #2

P: n/a
Marcio Rosa da Silva wrote:
In other words, it is safe to do:
dd = dict(zip(d.values(),d.keys()))

to exchange keys and values on a dictionary?


See the Library Reference, section 2.3.8 Mapping Types:
Keys and values are listed in an arbitrary order which is non-random,
varies across Python implementations, and depends on the dictionary's
history of insertions and deletions. If items(), keys(), values(),
iteritems(), iterkeys(), and itervalues() are called with no
intervening modifications to the dictionary, the lists will directly
correspond. This allows the creation of (value, key) pairs using
zip(): "pairs = zip(a.values(), a.keys())". The same relationship
holds for the iterkeys() and itervalues() methods: "pairs =
zip(a.itervalues(), a.iterkeys())" provides the same value for pairs.
Another way to create the same list is "pairs = [(v, k) for (k, v) in
a.iteritems()]".

Jul 19 '05 #3

P: n/a
Marcio Rosa da Silva wrote:
In dictionaries, unlinke lists, it doesn't matter the order one inserts the contents, elements are
stored using its own rules.

Ex:
d = {3: 4, 1: 2}
d

{1: 2, 3: 4}

So, my question is: if I use keys() and values() it will give me the keys and values in the same
order?


http://docs.python.org/lib/typesmapping.html

"Keys and values are listed in an arbitrary order which is non-random,
varies across Python implementations, and depends on the dictionary's
history of insertions and deletions. If items(), keys(), values(), iteritems(),
iterkeys(), and itervalues() are called with no intervening modifications
to the dictionary, the lists will directly correspond."

</F>

Jul 19 '05 #4

P: n/a
Thanks for the help!

Marcio
Jul 19 '05 #5

P: n/a
Marcio Rosa da Silva wrote:
So, my question is: if I use keys() and values() it will give me the
keys and values in the same order?
It should work fine with the current implementation of dictionaries, but
(AFAIK) it's not guaranteed to work by the mapping protocol. So
theoretically, it could break under Python 2.5 or with a user-made
mapping type.
Also, if someone has a better way to exchange keys and values in a dict,
I would like to learn. :-)


I would do it like this:
d = {1: 2, 2: 3, 3: 4}
d = dict([(value, key) for key, value in d.iteritems()])
d

{2: 1, 3: 2, 4: 3}
Jul 19 '05 #6

P: n/a
Here is a brute-force list comprehension that does not depend on
preserving order between dict.keys() and dict.values():

dict( [ (a[1],a[0]) for a in d.items() ] )

Or for map/lambda lovers:

rev = lambda a: (a[1],a[0])
dict( map( rev, d.items() )

But you still have no control over the order returned by d.items(), so
if your initial dict has duplicate values, there is no telling which
key a duplicate would map to.

The real general-purpose dict inversion results in a dict with each
value containing a list of keys in the original dict that mapped to the
given value. That is:
d = {3: 4, 1: 2, 0:4}
would invert to:
d2 = { 2:[1], 4:[0,3] }

I couldn't cram this into a list comp, so here is a short for loop to
create d2:
d2 = {}
for k,v in d.items():
d2[v] = d2.get(v, list()) + [k]

-- Paul

Jul 19 '05 #7

P: n/a
Marcio Rosa da Silva wrote:
Hi!

In dictionaries, unlinke lists, it doesn't matter the order one inserts
the contents, elements are stored using its own rules.

Ex:
>>> d = {3: 4, 1: 2}
>>> d {1: 2, 3: 4}

So, my question is: if I use keys() and values() it will give me the
keys and values in the same order?

In other words, it is safe to do:
>>> dd = dict(zip(d.values(),d.keys()))
to exchange keys and values on a dictionary? Or I can have the values
and keys in a different order and end with something like this:
>>> dd {2: 3 , 4: 1}

instead of:
>>> dd

{2: 1, 4: 3}

For this example it works as I wanted (the second output), but can I
trust this?

Also, if someone has a better way to exchange keys and values in a dict,
I would like to learn. :-)

Thanks!

Marcio


Well, a footnote to the "Mapping types" page in the Library Reference says

"""Keys and values are listed in an arbitrary order which is non-random,
varies across Python implementations, and depends on the dictionary's
history of insertions and deletions. If items(), keys(), values(),
iteritems(), iterkeys(), and itervalues() are called with no intervening
modifications to the dictionary, the lists will directly correspond.
This allows the creation of (value, key) pairs using zip(): "pairs =
zip(a.values(), a.keys())". The same relationship holds for the
iterkeys() and itervalues() methods: "pairs = zip(a.itervalues(),
a.iterkeys())" provides the same value for pairs. Another way to create
the same list is "pairs = [(v, k) for (k, v) in a.iteritems()]". """

So it looks as though you will be safe, since there's a promise in the
documentation.

If you just want to iterate over the (key, value) pairs, however, you
should normally choose items() or iteritems() to do so. Then you could
use (for example):

dd = dict((x[1], x[0]) for x in d.items())

I presume you are confident that each value will only occur once in the
original dictionary, as otherwise the result will be smaller than the input.

regards
Steve
--
Steve Holden +1 703 861 4237 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/

Jul 19 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.