Tricky Dictionary Question from newbie

R

Ric Da Force

Hi all,

I have a dictionary containing about 300 items, some of the values being
repeated. Both keys and values are strings. How can I turn this thing on
its head so that we create a key based on each unique value and build the
values based on the keys corresponding to the repeated values?

It is hard to explain but this is what I mean:

Dict = {'rt': 'This is repeated', 'sr': 'This is repeated', 'gf': 'This is
not'}

I want this to return a new dict with string keys and lists containing the
previous keys for repeated values.

NewDict = {'This is repeated':['rt','sr'],'This is not':['gf']}

I am still learning Python and have struggled with this for hours before
deciding to go for help. Unfortunately, I didn't really know how to search
for this in google and decided to post it here. I apologise if this is too
basic for this newsgroup...

Ric
 
M

Mark Jackson

Ric Da Force said:
It is hard to explain but this is what I mean:

Dict = {'rt': 'This is repeated', 'sr': 'This is repeated', 'gf': 'This is
not'}

I want this to return a new dict with string keys and lists containing the
previous keys for repeated values.

NewDict = {'This is repeated':['rt','sr'],'This is not':['gf']}

NewDict = {}
for x in Dict.keys():
try:
NewDict[Dict[x]].append(x)
except KeyError:
NewDict[Dict[x]] = [x]
 
M

Markus Weihs

Hi!


Dict = {'rt': 'repeated', 'sr':'repeated', 'gf':'not repeated'}
NewDic = {}

for k,v in Dict.items():
NewDic.setdefault(v, []).append(k)


Regards, mawe
 
R

Reinhold Birkenfeld

Mark said:
Ric Da Force said:
It is hard to explain but this is what I mean:

Dict = {'rt': 'This is repeated', 'sr': 'This is repeated', 'gf': 'This is
not'}

I want this to return a new dict with string keys and lists containing the
previous keys for repeated values.

NewDict = {'This is repeated':['rt','sr'],'This is not':['gf']}

NewDict = {}
for x in Dict.keys():
try:
NewDict[Dict[x]].append(x)
except KeyError:
NewDict[Dict[x]] = [x]

Or, more up-to-date:

NewDict = {}
for key, val in Dict.iteritems():
NewDict.setdefault(val, []).append(key)

Reinhold
 
R

Ric Da Force

Thank you guys! (Reinhold, Mark and Markus) I must confess that I am
absolutely awe struck at the power of this language! There is no way in the
world that I would have envisaged such simple and elegant solutions!!!

Reinhold, is your solution specific to 2.4?

Kind Regards,

Ric

Reinhold Birkenfeld said:
Mark said:
Ric Da Force said:
It is hard to explain but this is what I mean:

Dict = {'rt': 'This is repeated', 'sr': 'This is repeated', 'gf': 'This
is
not'}

I want this to return a new dict with string keys and lists containing
the
previous keys for repeated values.

NewDict = {'This is repeated':['rt','sr'],'This is not':['gf']}

NewDict = {}
for x in Dict.keys():
try:
NewDict[Dict[x]].append(x)
except KeyError:
NewDict[Dict[x]] = [x]

Or, more up-to-date:

NewDict = {}
for key, val in Dict.iteritems():
NewDict.setdefault(val, []).append(key)

Reinhold
 
R

Ric Da Force

How does setdefault work exactly? I am looking in the docs and can't figure
it out...
Ric

Ric Da Force said:
Thank you guys! (Reinhold, Mark and Markus) I must confess that I am
absolutely awe struck at the power of this language! There is no way in
the world that I would have envisaged such simple and elegant solutions!!!

Reinhold, is your solution specific to 2.4?

Kind Regards,

Ric

Reinhold Birkenfeld said:
Mark said:
It is hard to explain but this is what I mean:

Dict = {'rt': 'This is repeated', 'sr': 'This is repeated', 'gf': 'This
is
not'}

I want this to return a new dict with string keys and lists containing
the
previous keys for repeated values.

NewDict = {'This is repeated':['rt','sr'],'This is not':['gf']}

NewDict = {}
for x in Dict.keys():
try:
NewDict[Dict[x]].append(x)
except KeyError:
NewDict[Dict[x]] = [x]

Or, more up-to-date:

NewDict = {}
for key, val in Dict.iteritems():
NewDict.setdefault(val, []).append(key)

Reinhold
 
P

Peter Hansen

Ric said:
How does setdefault work exactly? I am looking in the docs and can't figure
it out...

If the key (the first argument) already exists in the dictionary, the
corresponding value is returned. If the key does not exist in the
dictionary, it is stored in the dictionary and bound to the second
argument, and then that second argument is returned as the value.

(I always have to ignore the name to think about how it works, or it
gets in the way of my understanding it. The name makes fairly little
sense to me.)

-Peter
 
D

Dennis Lee Bieber

How does setdefault work exactly? I am looking in the docs and can't figure
it out...

If the "key" exists in the dictionary, the value associated is
returned, other the value is set to the supplied default which is then
returned.

In your case, "key" is the "value" of the existing dictionary
entry...

d1 = {"a":"1", "b":"2", "c":"1"}
d2 = {}
For each key/value pair (say: key="a", value="1") in d1

d2.setdefault(value, []).append(key)

is looking for d2["1"]; if it isn't found, it returns an empty list and
appends "a" to it.

After "a" and "b" it looks like:

{"1":["a"], "2":["b"]}... now run the pair "c"/"1"

"1" is found, so returns ["a"] to which "c" is appended

--
 
J

James Carroll

Notice the dictionary is only changed if the key was missing.
{'a': '1', 'b': '3'}

-Jim
 
P

Peter Hansen

(Fixed top-posting)

Notice the dictionary is only changed if the key was missing.

James, I'll assume your reply was intended to address my comment above.

It's not so much that the concept of "set the default value for this
key" is poorly captured by the name "setdefault", but that the function
is used almost exclusively in the idiom below, where it is critical that
it also _returns_ the value, which is usually then operated on
immediately, usually in the same line of code.

dict.setdefault(key, defaultValue).someMethodOnKey()

or

dict.setdefault(key, defaultValue) #= value, where # is some operator.

I suppose I shouldn't blame setdefault() itself for being poorly named,
but it's confusing to me each time I see it in the above, because the
name doesn't emphasize that the value is being returned, and yet that
fact is arguably more important than the fact that a default is set!

I can't think of a better name, though, although I might find "foo" less
confusing in the above context. :)

-Peter
 
J

James Carroll

Oops.. Gmail just normally puts the reply to at the bottom of the
discussion... so by default I reply to the list, and the last person
to post. My comment was not directed at you. I just posted the
contents of an interactive session that I did to better understand
setdefault myself. I've got to remind myself to change the reply-to
address to the list. (other lists do this by default, why not this
one?)

I agree that the name doesn't ring quite right to me either.

I kind of understand what the creator of the function was getting
at... it's kind of like when you want to retrieve a configuration
variable from a container, but if it's not there, then you want to use
a default:

storedWidth = container.GetConfigurationValue(name = "width", default=500)

If there is a width stored, it will retrieve that, otherwise it will
give you the default that you specified in the second parameter. It
makes it easier than checking for existance, then retrieving or
assigning a default.

Setdefault, in my mind is really a _get_ kind of operation. It
retrieves from the dictionary most of the time, and only does anything
different when the key doesn't exist, and then does an assignment...

so my next guess at a better name for setdefault would be:

value = container.GetOrAddDefault(key="a", default=[])
value.append(listvalue)

but that's kind of confusing too, but it better describes what is happening..

-Jim
 
T

Tim Peters

[Peter Hansen]
....
I suppose I shouldn't blame setdefault() itself for being poorly named,

No said:
but it's confusing to me each time I see it in the above, because the
name doesn't emphasize that the value is being returned, and yet that
fact is arguably more important than the fact that a default is set!

I can't think of a better name, though, although I might find "foo" less
confusing in the above context. :)

I wanted to call it getorset() -- so much so that even now I sometimes
still type that instead! The "get" part reminds me that it's fetching
a value, same as dict.get(key, default) -- "or set"'ing it too if
there's not already a value to "get". If you have a fancy enough
editor, you can teach it to replace setdefault by getorset whenever
you type the former ;-)
 
B

Bengt Richter

[Peter Hansen]
...
I suppose I shouldn't blame setdefault() itself for being poorly named,

No said:
but it's confusing to me each time I see it in the above, because the
name doesn't emphasize that the value is being returned, and yet that
fact is arguably more important than the fact that a default is set!

I can't think of a better name, though, although I might find "foo" less
confusing in the above context. :)

I wanted to call it getorset() -- so much so that even now I sometimes
still type that instead! The "get" part reminds me that it's fetching
a value, same as dict.get(key, default) -- "or set"'ing it too if
there's not already a value to "get". If you have a fancy enough
editor, you can teach it to replace setdefault by getorset whenever
you type the former ;-)

But it isn't get OR set, it's
set_default_if_no_value_then_either_way_effectively_get ;-)
Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

New to python 4
Dictionary help 1
Help with an algorythm 5
Advanced Dictionary 6
Issue values dictionary 4
Sorted dictionary 7
Creating a dictionary from a .txt file 18
Iterating Through Dictionary of Lists 2

Members online

Forum statistics

Threads
474,261
Messages
2,571,308
Members
47,970
Latest member
DelGamboa0

Latest Threads

Top