3

I'd like to find the amount of values within sequences of the same value from a list:

list = ['A','A','A','B','B','C','A','A']

The result should look like:

result_dic = {A: [3,2], B: [2], C: [1]}

I do not just want the counts of different values in a list as you can see in the result for A.

monart
  • 129
  • 1
  • 10
  • 2
    Possible duplicate of [How to count the occurrences of a list item?](https://stackoverflow.com/questions/2600191/how-to-count-the-occurrences-of-a-list-item) – Dragonthoughts Nov 13 '18 at 13:01
  • 1
    It's not a duplicate of that, he's looking for specifically when a duplicate comes after each other unbroken by non duplicates. I'd suggest a [DefaultDict](https://docs.python.org/2/library/collections.html#collections.defaultdict) – Jab Nov 13 '18 at 13:03

3 Answers3

3

collections.defaultdict and itertools.groupby

from itertools import groupby
from collections import defaultdict

listy = ['A','A','A','B','B','C','A','A']

d = defaultdict(list)

for k, v in groupby(listy):
  d[k].append(len([*v]))

d

defaultdict(list, {'A': [3, 2], 'B': [2], 'C': [1]})

  • groupby will loop through an iterable and lump contiguous things together.

    [(k, [*v]) for k, v in groupby(listy)]
    
    [('A', ['A', 'A', 'A']), ('B', ['B', 'B']), ('C', ['C']), ('A', ['A', 'A'])]
    
  • So I loop through those results and append the length of each grouped thing to the values of a defaultdict

piRSquared
  • 285,575
  • 57
  • 475
  • 624
  • 2
    I like that you used `groupby`, better and more readable than my approach. – Jab Nov 13 '18 at 13:34
  • 1
    Thanks @Jaba. However, some people like to see the logic laid out. Your answer is a good one as well. – piRSquared Nov 13 '18 at 13:35
  • 1
    Alternative (to avoid intermediary lists that are then discarded): instead of `len([*v])` you can use `sum(1 for _ in v)`. – jpp Nov 13 '18 at 23:59
2

I'd suggest using a defaultdict and looping through the list.

from collections import defaultdict

sample = ['A','A','A','B','B','C','A','A']

result_dic = defaultdict(list)
last_letter = None
num = 0

for l in sample:
    if last_letter == l or last_letter is None:
        num += 1
    else:
        result_dic[last_letter].append(num)

Edit This is my approach, although I'd have a look at @piRSquared's answer because they were keen enough to include groupby as well. Nice work!

Jab
  • 26,853
  • 21
  • 75
  • 114
0

I'd suggest looping through the list.

result_dic = {}
old_word = ''

for word in list:
    if not word in result_dic:
        d[word] = [1]
    elif word == old_word:
        result_dic[word][-1] += 1
    else:
        result_dic[word].append(1)
    old_word = word
Q-life
  • 74
  • 6
  • Please explain your approach when answering, don't just put code in. This is lazy and doesn't do much for the OP – Jab Nov 13 '18 at 13:35
  • I'm not lazy, never have been. But I don't see the point of describing such a simple code snippet. Especially with such a verbose language as python. It's like writing the same code twice but in different language. Don't see the point of people having to read the same thing twice. Rest assured if I post something more complicated I will add ample explanations. – Q-life Nov 13 '18 at 13:43
  • 1
    I did not say you were lazy, what I meant was that if someone is asking as "simple" a question as this, then some explanation as to what your code does is much more helpful for them than just a code snippet, also it's a part of [how to answer a question](https://stackoverflow.com/help/how-to-answer). Again, you aren't wrong, just not as helpful when answering only code. – Jab Nov 13 '18 at 14:00