473,379 Members | 1,235 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,379 software developers and data experts.

'inverting' a dict

Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.

Jul 18 '05 #1
15 1839
Irmen de Jong wrote:
Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.


It's seems like rather nice Python for me ;). Two more variants:

inverted = {}
for k, vs in d.iteritems():
inverted.update(dict([(v, k) for v in vs]))

map(
lambda (k, vs): inverted.update(dict([(v, k) for v in vs])),
d.iteritems()
)

happy new year,
anton.
Jul 18 '05 #2
On Tue, 30 Dec 2003 18:30:56 +0100, Irmen de Jong
<irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote:
Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.


I had a need for a 'reverse' dictionary also. This is how I approached
it:

source_dict = {'A': 1,'B': 2,'C': 3,'D': 4}
target_dict = {}
for item in source_dict.iteritems():
target_dict[item[1]] = item[0]

Or, a bit more contrived....

source_dict = {'A': [[1,2,3],100],'B': [[4,5,6],200],'C':
[[7,8,9],300]}
target_dict = {}
for item in source_dict.iteritems():
target_dict[item[1][1]] = item[0]

Disclaimer: I'm a newbie
Norm
Jul 18 '05 #3
or even shorter
d = {'key1' : ('value1','value2'), 'key2': ('value3',) } dict([(v,k) for k in d.iterkeys() for v in d[k]])
{'value3': 'key2', 'value2': 'key1', 'value1': 'key1'}
"anton muhin" <an********@rambler.ru> a écrit dans le message de
news:bs************@ID-217427.news.uni-berlin.de Irmen de Jong wrote:
Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.


It's seems like rather nice Python for me ;). Two more variants:

inverted = {}
for k, vs in d.iteritems():
inverted.update(dict([(v, k) for v in vs]))

map(
lambda (k, vs): inverted.update(dict([(v, k) for v in vs])),
d.iteritems()
)

happy new year,
anton.

Jul 18 '05 #4
Irmen de Jong wrote:
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:
[...]
What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)


Here's what I've come up with:

import itertools

original = {"key1": ("value1", "value2"), "key2": ("value3",)}

def forInv(original):
result = {}
for (key, values) in original.iteritems():
for val in values:
result[val] = key
return result

def updateInv(original):
result = {}
for (key, values) in original.iteritems():
result.update(dict.fromkeys(values, key))
return result

def iterInv(original):
result = {}
for (key, values) in original.iteritems():
result.update(dict(itertools.izip(values, itertools.repeat(key))))
return result

def iterInv2(original):
return dict(itertools.chain(*[itertools.izip(values,
itertools.repeat(key))
for key, values in original.iteritems()]))

def compInv(original):
return dict([(val, key) for (key, values) in original.iteritems() for
val in values])

wanted = { "value1": "key1", "value2": "key1", "value3": "key2" }

for inv in globals().values():
if callable(inv):
print inv.__name__,
if inv(original) == wanted:
print "OK"
else:
print "FAILED"

Conclusion: my favourite toys, itertools and list comprehensions, lead to
clumsier code - well, me at least. So I would recommend that you don't
listen to that voice.

Peter
Jul 18 '05 #5
Does this listcomp give the right result?
dict([(v, k) for k, vs in original.iteritems() for v in vs])

Jeff

Jul 18 '05 #6
Irmen de Jong <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message news:<3f*********************@news.xs4all.nl>...
Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.

def invert_dict(D):
return dict([(y,x) for (x,y) in D.items()])

-- Wade Leftwich
Ithaca, NY
Jul 18 '05 #7
Yermat wrote:
or even shorter
d = {'key1' : ('value1','value2'), 'key2': ('value3',) }
dict([(v,k) for k in d.iterkeys() for v in d[k]])


{'value3': 'key2', 'value2': 'key1', 'value1': 'key1'}


Yep, thanks, that must have been the solution that I was looking for!
I understand list comprehensions, but keep forgetting about the
multiple-loop-kind.

--Irmen.

Jul 18 '05 #8
Jeff Epler wrote:
Does this listcomp give the right result?
dict([(v, k) for k, vs in original.iteritems() for v in vs])


Yes it does, and it's even more concise than Yermat's solution

dict([(v,k) for k in d.iterkeys() for v in d[k]])

because it avoids a dict lookup every loop cycle. Thanks Jeff!

--Irmen

Jul 18 '05 #9
Wade Leftwich wrote:
def invert_dict(D):
return dict([(y,x) for (x,y) in D.items()])


No, this one only works for non-sequence-type values.
I wanted to map every item of a value (a sequence)
to the corresponding key.

--Irmen

Jul 18 '05 #10
dict2=dict([(a,b) for b in dict1.keys() for a in dict1[b]])

HTH
"Irmen de Jong" <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message
news:3f*********************@news.xs4all.nl...
| Hi
| I have this dict that maps a name to a sequence of other names.
| I want to have it reversed, i.e., map the other names each to
| the key they belong to (yes, the other names are unique and
| they only occur once). Like this:
|
| { "key1": ("value1", "value2"), "key2": ("value3,) }
|
| -->
|
| { "value1": "key1", "value2": "key1", "value3": "key2" }
|
| What I'm doing is using a nested loop:
|
| dict2={}
| for (key,value) in dict1.items():
| for name in value:
| dict2[name] = key
|
| which is simple enough, but I'm hearing this little voice in
| the back of my head saying "there's a simpler solution".
| Is there? What is it? ;-)
|
| Thanks
| --Irmen.
|
Jul 18 '05 #11

This is sort of off topic for the thread, but I've got a similar
problem. In this case I have a dict like:

{ 'key1': 'value1', 'key2': value2}

and I sometimes need to find the key for the value. All values/keys are
unique. I just use a loop:

for a in dict:
if dict[a]== targ:
return a
return None

But it'd be nice to have something faster, etc.
Elaine Jackson wrote:
dict2=dict([(a,b) for b in dict1.keys() for a in dict1[b]])

HTH
"Irmen de Jong" <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message
news:3f*********************@news.xs4all.nl...
| Hi
| I have this dict that maps a name to a sequence of other names.
| I want to have it reversed, i.e., map the other names each to
| the key they belong to (yes, the other names are unique and
| they only occur once). Like this:
|
| { "key1": ("value1", "value2"), "key2": ("value3,) }
|
| -->
|
| { "value1": "key1", "value2": "key1", "value3": "key2" }
|
| What I'm doing is using a nested loop:
|
| dict2={}
| for (key,value) in dict1.items():
| for name in value:
| dict2[name] = key
|
| which is simple enough, but I'm hearing this little voice in
| the back of my head saying "there's a simpler solution".
| Is there? What is it? ;-)
|
| Thanks
| --Irmen.
|


--
Bob van der Poel ** Wynndel, British Columbia, CANADA **
EMAIL: bv*****@kootenay.com
WWW: http://www.kootenay.com/~bvdpoel

Jul 18 '05 #12
Irmen de Jong <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message news:<3f*********************@news.xs4all.nl>...
Wade Leftwich wrote:
def invert_dict(D):
return dict([(y,x) for (x,y) in D.items()])


No, this one only works for non-sequence-type values.
I wanted to map every item of a value (a sequence)
to the corresponding key.

--Irmen


Try a nested list comprehension:
data = { "key1": ("value1", "value2"), "key2": ("value3",) }
dict([(v,k) for k,vlist in data.iteritems() for v in vlist]) {'value3': 'key2', 'value2': 'key1', 'value1': 'key1'}
Raymond Hettinger

P.S. In Py2.4, it will be possible to write this without the
brackets. The resulting generator expression is faster and more
memory friendly:
dict((v,k) for k,vlist in data.iteritems() for v in vlist)

{'value3': 'key2', 'value2': 'key1', 'value1': 'key1'}
Jul 18 '05 #13
Irmen de Jong <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> wrote in message news:<3f*********************@news.xs4all.nl>...
Hi
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:

{ "key1": ("value1", "value2"), "key2": ("value3,) }

-->

{ "value1": "key1", "value2": "key1", "value3": "key2" }

What I'm doing is using a nested loop:

dict2={}
for (key,value) in dict1.items():
for name in value:
dict2[name] = key

which is simple enough, but I'm hearing this little voice in
the back of my head saying "there's a simpler solution".
Is there? What is it? ;-)

Thanks
--Irmen.


.... and after all there is always a hacky one-liner:
org = {"key1": ("value1", "value2"), "key2": ("value3",)}
dict(reduce(lambda l,(k,v):l.extend(zip(v,(k,)*len(v))) or l,org.items(),[])) {'value3': 'key2', 'value2': 'key1', 'value1': 'key1'}


Happy new year
Peter
Jul 18 '05 #14
sdd
Bob van der Poel wrote:
This is sort of off topic for the thread, but I've got a similar
problem. In this case I have a dict like:

{ 'key1': 'value1', 'key2': value2}

and I sometimes need to find the key for the value. All values/keys are
unique. I just use a loop:

for a in dict:
if dict[a]== targ:
return a
return None

For a few hunts, I'd do:
for key,value in dictionary.iteritems():
if value == target:
return key
return None

Of course, if it probed a lot between changes, it's better to

reversedictionary = dict([(v,k) for k,v in dictionary.items()])

-Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #15
Irmen de Jong <irmen@-NOSPAM-REMOVETHIS-xs4all.nl> writes:
I have this dict that maps a name to a sequence of other names.
I want to have it reversed, i.e., map the other names each to
the key they belong to (yes, the other names are unique and
they only occur once). Like this:


That's almost spooky, I'm working on a project for which I needed
something like this. I've just read the entire thread and my solution
seems pretty naive:

def invertdict(d):
"""Returns a dict whose key-value pairs are the value-key pairs of d."""
ret = {}
for k in d:
ret[d[k]] = k
return ret

I only need to do it once or twice, at program start-up, so time-
efficiency wasn't a critical factor. I'm guessing the list
comprehension tactics are faster, though.

Sorry about being late to the party, I've been away from Usenet for
about three weeks...

Nick

--
# sigmask || 0.2 || 20030107 || public domain || feed this to a python
print reduce(lambda x,y:x+chr(ord(y)-1),' Ojdl!Wbshjti!=obwAcboefstobudi/psh?')
Jul 18 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: Robin Cull | last post by:
Imagine I have a dict looking something like this: myDict = {"key 1": , "key 2": , "key 3": , "key 4": } That is, a set of keys which have a variable length list of associated values after...
1
by: spalding | last post by:
One issue I've had is successfully searching for regular expression documentation outlining the approach to inverting the test (ie. returning true in the case that the expression is not found)....
3
by: Bengt Richter | last post by:
Has anyone found a way besides not deriving from dict? Shouldn't there be a way? TIA (need this for what I hope is an improvement on the Larosa/Foord OrderedDict ;-) I guess I can just document...
11
by: sandravandale | last post by:
I can think of several messy ways of making a dict that sets a flag if it's been altered, but I have a hunch that experienced python programmers would probably have an easier (well maybe more...
15
by: Cruella DeVille | last post by:
I'm trying to implement a bookmark-url program, which accepts user input and puts the strings in a dictionary. Somehow I'm not able to iterate myDictionary of type Dict{} When I write print...
15
by: George Sakkis | last post by:
Although I consider dict(**kwds) as one of the few unfortunate design choices in python since it prevents the future addition of useful keyword arguments (e.g a default value or an orderby...
12
by: jeremito | last post by:
Please excuse me if this is obvious to others, but I can't figure it out. I am subclassing dict, but want to prevent direct changing of some key/value pairs. For this I thought I should override...
2
by: bpowah | last post by:
I searched for an hour and don't see a solution to this (i assume somewhat common) problem. I have a very large dictionary of lists: d = {a:, b:, c:} and i want to reverse the associativity of...
1
by: | last post by:
Hello all, I have a question which might be simple or need some work around. I want to do something like this. My class/instance has a dict as a property. I want the instance to catch the...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.