简体   繁体   中英

Python: split list into indices based on consecutive identical values

If you could advice me how to write the script to split list by number of values I mean:

my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 

And there are 11-4,12-2,15-6,20-3 items. So in next list for exsample range(0:100) I have to split on 4,2,6,3 parts So I counted same values and function for split list, but it doen't work with list:

 div=Counter(my_list).values() ##counts same values in the list

 def chunk(it, size):
    it = iter(it)
    return iter(lambda: tuple(islice(it, size)), ())

What do I need:

Out: ([0,1,2,3],[4,5],[6,7,8,9,10,11], etc...] 

You can use enumerate , itertools.groupby , and operator.itemgetter :

In [45]: import itertools

In [46]: import operator

In [47]: [[e[0] for e in d[1]] for d in itertools.groupby(enumerate(my_list), key=operator.itemgetter(1))]
Out[47]: [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14]]

What this does is as follows:

  1. First it enumerates the items.

  2. It groups them, using the second item in each enumeration tuple (the original value).

  3. In the resulting list per group, it uses the first item in each tuple (the enumeration)

Solution in Python 3 , If you are only using counter :

from collections import Counter
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 
count = Counter(my_list)
div= list(count.keys())         # take only keys
div.sort()
l = []
num = 0
for i in div:
    t = []
    for j in range(count[i]):   # loop number of times it occurs in the list
        t.append(num)
        num+=1
    l.append(t)
print(l)

Output:

[[0, 1, 2, 3], [4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14]]

Alternate Solution using set :

my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 
val = set(my_list)                     # filter only unique elements
ans = []
num = 0
for i in val:
    temp = []
    for j in range(my_list.count(i)):   # loop till number of occurrence of each unique element
        temp.append(num)
        num+=1
    ans.append(temp)
print(ans)

EDIT: As per required changes made to get desired output as mention in comments by @Protoss Reed

my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20] 
val = list(set(my_list))                     # filter only unique elements
val.sort()                                   # because set is not sorted by default
ans = []
index = 0
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in val:
    temp = []
    for j in range(my_list.count(i)):   # loop till number of occurrence of each unique element
        temp.append(l2[index])
        index+=1
    ans.append(temp)
print(ans)

Output:

[[54, 21, 12, 45], [78, 41], [235, 7, 10, 4, 1, 1], [897, 5, 79]]

Here I have to convert set into list because set is not sorted and I think remaining is self explanatory.

Another Solution if input is not always Sorted (using OrderedDict ):

from collections import OrderedDict
v = OrderedDict({})
my_list=[12,12,11,11,11,11,20,20,20,15,15,15,15,15,15]
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in my_list:                # maintain count in dict
    if i in v:
        v[i]+=1
    else:
        v[i]=1
ans =[]
index = 0
for key,values in v.items():
    temp = []
    for j in range(values):
        temp.append(l2[index])
        index+=1
    ans.append(temp)
print(ans)

Output:

[[54, 21], [12, 45, 78, 41], [235, 7, 10], [4, 1, 1, 897, 5, 79]]

Here I use OrderedDict to maintain order of input sequence which is random(unpredictable) in case of set .

Although I prefer @Ami Tavory's solution which is more pythonic.

[Extra work: If anybody can convert this solution into list comprehension it will be awesome because i tried but can not convert it to list comprehension and if you succeed please post it in comments it will help me to understand]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM