12

I have a list as follows, consisting of only (-1)s and 1s:

list1=[-1,-1,1,1,1,-1,1]

I'm trying to append the number of consecutive duplicates into a list, e.g.:

count_dups=[2,3,1,1] 

I've tried creating a new list and using the zip function as the first step, but can't seem to go on because of the cut-off end-value

list2=list1[1:]
empty=[]
for x,y in zip(list1,list2):
    if x==y:
        empty.append(x)
    else:
        empty.append(0)
idjaw
  • 25,487
  • 7
  • 64
  • 83
Cameron Hiruta
  • 133
  • 1
  • 1
  • 4

3 Answers3

26

You can use itertools.groupby:

from itertools import groupby
list1 = [-1, -1, 1, 1, 1, -1, 1]
count_dups = [sum(1 for _ in group) for _, group in groupby(list1)]
print(count_dups)

Output:

[2, 3, 1, 1]
Karin
  • 8,404
  • 25
  • 34
  • 1
    `len(list(group))` will tend to be faster on small sequences, but if you had a really large iterable with large consecutive values, then it might be worth considering `sum(1 for _ in group)` instead. – Jon Clements Sep 06 '16 at 03:54
  • I was just editing this to use the iterator instead of casting to a list =D Yes - I agree. – Karin Sep 06 '16 at 03:56
  • 3
    FWIW, re-using the variable name `_` inside the `sum` generator expression as well as in the outer part of the list comprehension _might_ be confusing to new coders, especially if they aren't familiar with the convention of using `_` as a throwaway name in loops. So you might like to mention that the two uses of `_` are independent of each other. – PM 2Ring Sep 06 '16 at 08:01
  • @PM2Ring Personally, I'd rename `_, group` to `_k, group` cause I often forget what `groupby()` yields. – wjandrea Aug 17 '22 at 15:58
2
def count_dups(L):
    ans = []
    if not L:
        return ans
    running_count = 1
    for i in range(len(L)-1):
        if L[i] == L[i+1]:
            running_count += 1
        else:
            ans.append(running_count)
            running_count = 1
    ans.append(running_count)
    return ans
BallpointBen
  • 9,406
  • 1
  • 32
  • 62
1
def count_dups(lst):
    return reduce(
        lambda a,b: (((a[-1] == b) and (a[:-2] + [a[-2]+1,a[-1]])) or (a[:-1] + [1,b])) ,
        lst[1:] ,
        [1,lst[0]]
    )[:-1]
J Earls
  • 1,792
  • 8
  • 12