views:

84

answers:

3

List.

['Chrome', 'Chromium', 'Google', 'Python']

Result.

{'C': ['Chrome', 'Chromium'], 'G': ['Google'], 'P': ['Python']}

I can make it work like this.

alphabet = dict()
for name in ['Chrome', 'Chromium', 'Google', 'Python']:
  character = name[:1].upper()
  if not character in alphabet:
    alphabet[character] = list()
  alphabet[character].append(name)

It is probably a bit faster to pre-populate the dictionary with A-Z, to save the key check on every name, and then afterwards delete keys with empty lists. I'm not sure either is the best solution though.

Is there a pythonic way to do this?

+5  A: 

I don't know if it's Pythonic, but it's more succinct:

import itertools
def keyfunc(x):
   return x[:1].upper()
l = ['Chrome', 'Chromium', 'Google', 'Python']
l.sort(key=keyfunc)
dict((key, list(value)) for (key,value) in itertools.groupby(l, keyfunc))

EDIT 2 made it less succinct than previous version, more readable and more correct (groupby works as intended only on sorted lists)

Amnon
and it's elligible for obfuscated code contest
Antoine Pelisse
@Antoine: I hope not. The groupby makes the intention pretty clear.
Amnon
In making it correct, you also made it way less efficient. I would pretty much can `groupby` and roll with a one pass solution at this point.
aaronasterling
+6  A: 

Anything wrong with this? I agree with Antoine, the oneliner solution is rather cryptic.

import collections

alphabet = collections.defaultdict(list)
for word in words:
    alphabet[word[0].upper()].append(word)
delnan
This is a lot better imo
Antoine Pelisse
It's the first thing that came to my mind.
aaronasterling
A: 

I would do it like this-

import string

#init thedict
group_d = dict((letter, []) for letter in string.ascii_uppercase)

#populate the dict
[group_d[x[0].upper()].append(x) for x in ['Chrome','Chromium','Google','Python']]

This updates your dict.

UPDATE: Some of them seem bent-out-of shape since I used list-comprehension for "side-effect". So one can do it like this also -

import string

group_d = dict((letter, []) for letter in string.ascii_uppercase)
for x in ['Chrome','Chromium','Google','Python']:
    group_d[x[0].upper()].append(x)
MovieYoda
-1 Thou shalt not use list comprehensions for side effects.
delnan
what side effects?
MovieYoda
-1 thou shalt not append to `None`
aaronasterling
Changing the dictionary. List comprehensions are for - guess what - generating a list, not for turning loops into expressions. (Edit: And ++ for @aaronasterling, totally overlooked that one!)
delnan
what append to `None`. Please be clear.
MovieYoda
have you run the code? Or read it?
aaronasterling
You fixed the `AttributeError` but I'm still going to leave my -1. Your first version deserves it on two counts: the list comp for side effects and constructing a dict with every letter of the alphabet and the second one deserves it because if you were going to rip off delnan's answer, you should have used `setdefault` instead of, again, ... every ...
aaronasterling
The second version is just an updated one of the first. Nobody is ripping off anybody. I'll give you that there is redundancy in the dict.
MovieYoda
'ripoff' might have been a little harsh but both of them are delnan's solution (which had already been posted) severely crapified. Post superior duplicates, not inferior ones.
aaronasterling
aaron - i'll try.
MovieYoda