5
list1=['hello','hope','hate','hack','bit','basket','code','come','chess']

What I need is:

list2=[['hello','hope','hate','hack'],['bit','basket'],['code','come','chess']]

If the first character is the same and is the same group, then sublist it.

How can I solve this?

ekad
  • 14,436
  • 26
  • 44
  • 46
Lee_Prison
  • 239
  • 1
  • 3
  • 7

4 Answers4

16

You can use itertools.groupby:

>>> from itertools import groupby
>>> list1 = ['hello','hope','hate','hack','bit','basket','code','come','chess']
>>> [list(g) for k, g in groupby(list1, key=lambda x: x[0])]
[['hello', 'hope', 'hate', 'hack'], ['bit', 'basket'], ['code', 'come', 'chess']]
TerryA
  • 58,805
  • 11
  • 114
  • 143
  • @Lee_Prison Itertools is very cool :). Give it a look if you want; I linked the docs :) – TerryA Jul 26 '13 at 08:11
  • as an alternative to lambda, you may want to use `operator.itemgetter(0)` – njzk2 Jun 04 '14 at 19:28
  • 4
    This solution only works if the list is sorted. You could sort the list first, but performance would not be ideal. Is there another python lib that is more versatile? – josiah Sep 30 '14 at 03:33
  • 1
    @josiah maybe see my answer on that – nspo Apr 07 '17 at 20:17
1

Expanding on TerryA's answer:

To create a dict with the first letter as key and the matching elements as value, you can do

>>> list1=['hello','hope','hate','hack','bit','basket','code','come','chess', 'archetype', 'cheese']
... mydict={}
... for k, g in groupby(list1, key=lambda x: x[0]):
...    if k in mydict:
...        mydict[k] += g
...    else:
...        mydict[k]=list(g)
... print(mydict)
{'h': ['hello', 'hope', 'hate', 'hack'], 'b': ['bit', 'basket'], 'a': ['archetype'], 'c': ['code', 'come', 'chess', 'cheese']}

This also works if list1 is not sorted (as shown) and it can, of course, also be converted to a list of lists again with

>>> [v for k, v in mydict.items()]
[['hello', 'hope', 'hate', 'hack'], ['bit', 'basket'], ['archetype'], ['code', 'come', 'chess', 'cheese']]
nspo
  • 1,488
  • 16
  • 21
0

You can do that with partition_by function from my funcy library:

from funcy import partition_by
list2 = partition_by(0, list1)

Note that this will only work if list1 is already sorted, as with itertools.groupby. If list1 is unsorted than sorting it and then partitioning would be inefficient, the better way would be to use group_by function:

from funcy import group_by
list2 = group_by(0, list1).values()
Suor
  • 2,845
  • 1
  • 22
  • 28
0

In Python 3.7+ (i.e. a version where dictionaries maintain insertion order) you could simply use a dict of lists keyed by the first character to group the words. This works with both sorted and unsorted input:

list1 = ['hello', 'hope', 'hate', 'bit', 'basket', 'code', 'come', 'chess', 'hack']
d = {}

for word in list1:
    d.setdefault(word[0], []).append(word)
list2 = list(d.values())
print(list2)
# [['hello', 'hope', 'hate', 'hack'], ['bit', 'basket'], ['code', 'come', 'chess']]
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378