tags:

views:

1031

answers:

5

If I have a list in Python like

[1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]

how do I calculate the greatest number of repeats for any element? In this case 2 is repeated a maximum of 4 times and 1 is repeated a maximum of 3 times.

Is there a way to do this but also record the index at which the longest run began?

A: 

This code seems to work:

l = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]
previous = None

# value/repetition pair
greatest = (-1, -1)
reps = 1

for e in l:
    if e == previous:
        reps += 1
    else:
        if reps > greatest[1]:
            greatest = (previous, reps)

        previous = e
        reps = 1

if reps > greatest[1]:
    greatest = (previous, reps)

print greatest
Bastien Léonard
+1 for beating me to it.
geowa4
that's not what OP is asking
SilentGhost
OP even gave the test case...which your results don't match...
Jason Punyon
-1 to counter George's +1 on an incorrect answer
Sparr
I edited with a new algorithm. Please give me your advice.
Bastien Léonard
Err, apparently the OP wants the occurrences of every number. If the code above is correct, it should be easy to adapt it anyway.
Bastien Léonard
A: 

I'd use a hashmap of item to counter.

Every time you see a 'key' succession, increment its counter value. If you hit a new element, set the counter to 1 and keep going. At the end of this linear search, you should have the maximum succession count for each number.

Stefan Kendall
+2  A: 

Loop through the list, keep track of the current number, how many times it has been repeated, and compare that to the most times youve seen that number repeated.

Counts={}
Current=0
Current_Count=0
LIST = [1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1]
for i in LIST:
    if Current == i:
        Current_Count++
    else:
        Current_Count=1
        Current=i
    if Current_Count>Counts[i]:
        Counts[i]=Current_Count
print Counts
Sparr
+38  A: 

Use groupby, it group elements by value:

from itertools import groupby
group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1])
print max(group, key=lambda k: len(list(k[1])))

And here is the code in action:

>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1])
>>> print max(group, key=lambda k: len(list(k[1])))
(2, <itertools._grouper object at 0xb779f1cc>)
>>> group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3])
>>> print max(group, key=lambda k: len(list(k[1])))
(3, <itertools._grouper object at 0xb7df95ec>)

From python documentation:

The operation of groupby() is similar to the uniq filter in Unix. It generates a break or new group every time the value of the key function changes

# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D

If you also want the index of the longest run you can do the following:

group = groupby([1, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 3, 3, 3, 3, 3])
result = []
index = 0
for k, g in group:
   length = len(list(g))
   result.append((k, length, index))
   index += length

print max(result, key=lambda a:a[1])
Nadia Alramli
+1 — `groupby` is tailor-made for this.
Ben Blank
Is there a way to do this and also record the index at which the longest run began? Thanks!
hekevintran
I updated the answer with a solution to get the index as well
Nadia Alramli
Doesn't work with empty sequences, but nice solution anyway!
MartinStettner
+1 Great utilization of functional programming tools.
Adam Matan
+1  A: 

If you want it for just any element (i.e. the element with the most repetitions), you could use:

def f((v, l, m), x):
    nl = l+1 if x==v else 1
    return (x, nl, max(m,nl))

maxrep = reduce(f, l, (0,0,0))[2];

This only counts continuous repetitions (Result for [1,2,2,2,1,2] would be 3) and only records the element with the the maximum number.

Edit: Made definition of f a bit shorter ...

MartinStettner
Seems akin to a lot of Perl stuff? ;)
Lakshman Prasad