5

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...] 
Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
Protoss Reed
  • 265
  • 2
  • 6
  • 16
  • 1
    Checkout `itertools.groupby()` and `enumerate()`. – Ashwini Chaudhary Sep 12 '16 at 12:42
  • `def get_chunks(li, n): ; for i in range(0, len(li), n): ; yield li[i: i + n]` This slices list `li` to chunks of size `n` (the last chunk will have `<=n` values). See how you can modify it to fit your needs. – DeepSpace Sep 12 '16 at 12:45
  • @DeepSpace What is main problem, I can not use list like a size (n). l1=[3,2,4,] #size of parts`. and I need to split l2=[10,15,9,2,0,5,6,3,9]. Result shoulbe someting like this: res= [[10,15,9],[9,2],[0,6,3,9]] – Protoss Reed Sep 12 '16 at 13:51

2 Answers2

6

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)

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • Works well, but if I have already got the list which I should split? I mean: my_list (here i get number of parts) and in second list for instance my_data = [10,9,8,7,6,100,45,12,4] split. Actually I'm beginner so sorry for my silly question – Protoss Reed Sep 12 '16 at 13:09
  • My apologies. Not in front of a computer now, and will be able to look at this later . – Ami Tavory Sep 12 '16 at 13:16
  • =) No worries=)Take your time – Protoss Reed Sep 12 '16 at 13:21
2

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]

Kalpesh Dusane
  • 1,477
  • 3
  • 20
  • 27
  • Thank you for your help! Code works well, but Waht I acctully need from `my_list` number of parts (4,2,6,3) `div` or `set` does it good, but what is main question I have to split another list for exmaple `L2=[54.21,12,45,78,41,235,7,10,4,1,1,897,5,79]` And get result like: `res= [[ 54,21,12,45],[78,41],[235,7,10,4,1,1],[897,5,79]` – Protoss Reed Sep 12 '16 at 17:09
  • @Protoss Reed I made changes in the answer. Hope this helps. – Kalpesh Dusane Sep 12 '16 at 18:09
  • Heyy!that works perfect!thank you! You did a great job!But If you don't mind could you explain is this significant to sort list? Because i need only number of parts from it. But in special order. My_list is not always looks like that (sorted)it could be a random numbers. `my_list=[23,23,23,1,1,1,1,44,6542,6542..etc]` – Protoss Reed Sep 12 '16 at 18:53
  • @Protoss Reed Ohh i think it is always sorted. and one thing repeating numbers are always consecutive or random like `[1,1,22,5,22,1]`? – Kalpesh Dusane Sep 12 '16 at 19:07
  • They are random – Protoss Reed Sep 12 '16 at 19:26
  • @Protoss Reed set doesn't maintain the order so I apply `sort` but I again modified my answer, i think it will work – Kalpesh Dusane Sep 12 '16 at 19:30
  • @ Kalpesh Dusane I appreciate your help! Script works nice. I hope it will work when I try import ~1 000 000 rows from file =) – Protoss Reed Sep 12 '16 at 19:59