Falmarri
Falmarri

Reputation: 48559

Python dictionary creation syntax

I'm wondering if there's any way to populate a dictionary such that you have multiple keys mapping to the same value that's less verbose than say:

d = {1:'yes', 2:'yes', 3:'yes', 4:'no'}

I'm thinking something along the lines of:

d = {*(1,2,3):'yes', 4:'no'}

which is obviously a syntax error.

Is there a reasonably simple method of doing this without TOO much obfuscation? (I'm not playing code golf, but I also don't need to write essentially the same thing over and over. However, any code-golf related answers would be appreciated as well since code-golf is awesome =]).

Edit:

I probably picked a bad example. This is what I'm trying to do:

d = {*('READY', 95): 'GPLR2_95', 'CHARGING': 'GPLR3_99', 'PROTECTION': 'GPLR3_100', 'CONNECTED': 'GPLR3_101', 'ERROR':'GPLR3_102'}

What I would expect this to expand to is:

d = {'READY':'GPLR2_95', 95: 'GPLR2_95', ...}

Edit->Edit:

I know this is stupid and totally unnecessary, but my goal is to make this declaration on a single line. This obviously shouldn't limit any responses and writing code just because it fits on 1 line is stupid. But I'm writing a module level constant dict that would be nice if it was a single liner.

Upvotes: 56

Views: 113851

Answers (8)

d8xa
d8xa

Reputation: 23

How about this?

d = {
    **{k:'yes' for k in [1,2,3]},
    **{k:'no' for k in [4]}
}

It's less verbose than the accepted answer and more intuitive than inverting a dictionary.

Upvotes: 2

jhpg
jhpg

Reputation: 409

Try to iterate through the dict items.

  • For python 2.x

    {key: value for key, value in your_dict.iteritems()}

  • For python 3.x

    {key: value for key, value in your_dict.items()}

Upvotes: 1

Steven Rumbalski
Steven Rumbalski

Reputation: 45542

d = {'READY': 'GPLR2_95',
    95: 'GPLR2_95',
    'CHARGING': 'GPLR3_99',
    'PROTECTION': 'GPLR3_100',
    'CONNECTED': 'GPLR3_101',
    'ERROR':'GPLR3_102'}

What's wrong with breaking this into multiple lines (as above)? Is the point saving typing or saving vertical space? Something else?

BTW, it feels really strange to have keys that are a mix of numbers and strings.

note: I wrote this as an answer instead of a comment because I wanted to show formatted code on multiple lines.

Upvotes: 2

Tim Perevezentsev
Tim Perevezentsev

Reputation: 11

For your case

dict([(_, 'yes') for _ in range(1,4)], **{4:'no'})

And if you need multiple keys for 'yes' and 'no'

>>> from itertools import chain
>>> dict(chain([(_, 'yes') for _ in range(1,4)], [(_, 'no') for _ in range(4, 10)]))
{1: 'yes', 2: 'yes', 3: 'yes', 4: 'no', 5: 'no', 6: 'no', 7: 'no', 8: 'no', 9: 'no'}

Not so great, but works.

Upvotes: 1

Tim Pietzcker
Tim Pietzcker

Reputation: 336098

You could turn it around:

>>> d1 = {"yes": [1,2,3], "no": [4]}

and then "invert" that dictionary:

>>> d2 = {value:key for key in d1 for value in d1[key]}
>>> d2
{1: 'yes', 2: 'yes', 3: 'yes', 4: 'no'}

Upvotes: 90

Hyperboreus
Hyperboreus

Reputation: 32429

Code golf?

yesindices = [1,2,3,22,34,33]
noindices = [4,8,9]
dict (zip(yesindices, ['yes' for i in yesindices]) + zip(noindices, ['no' for i in noindices]))

yields

{1: 'yes', 2: 'yes', 3: 'yes', 4: 'no', 33: 'yes', 8: 'no', 9: 'no', 34: 'yes', 22: 'yes'}

Upvotes: 4

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798486

dict((x, {4: 'no'}.get(x, 'yes')) for x in range(1, 5))

Or in 3.x:

{x: {4: 'no'}.get(x, 'yes') for x in range(1, 5)}

Upvotes: 1

Charlie Martin
Charlie Martin

Reputation: 112356

How about:

501 $ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {"q":1}
>>> print a
{'q': 1}
>>> a["q"]
1
>>> a["r"] = a["s"] = a["t"] = 2
>>> a
{'q': 1, 's': 2, 'r': 2, 't': 2}
>>> 

Upvotes: 9

Related Questions