Max, len, split Python
<p>I'm trying to find all combinations of A,B repeated 3 times.
Once I've done this I would like to count how many A's there are in a row, by splitting the string and returning the len.max value. However this is going crazy on me. I must have misunderstood the len(max(tmp.split="A")</p>

<p>Can anyone explain what this really does (len returns the length of the string, and max returns the highest integer of that string, based on my split?) I expect it to return the number of A's in a row. "A,B,A" should return 1 even though there are two A's. </p>

<p>Suggestions and clarifications would be sincerely welcome</p>

<pre><code>import itertools
list = list(itertools.product(["A", "B"], repeat=3))

count = 0;

for i in list:
    count += 1;
    tmp = str(i);
    var = len(max(tmp.split("B")))
    print(count, i, var)
</code></pre>

<p>You can use <a href="https://docs.python.org/3/library/itertools.html#itertools.groupby" rel="nofollow"><code>itertools.groupby</code></a> to find groups of identical elements in an iterable. <code>groupby</code> generates a sequence of (key, group) tuples, where <code>key</code> is the value of the elements in the group, and <code>group</code> is an iterator of that group (which shares the underlying iterable with <code>groupby</code>. To get the length of the group we need to convert it to a list. </p>

<pre><code>from itertools import product, groupby

for t in product("AB", repeat=3):
    a = max([len(list(g)) for k, g in groupby(t) if k == "A"] or [0])
    print(t, a)
</code></pre>

<p><strong>output</strong></p>

<pre><code>('A', 'A', 'A') 3
('A', 'A', 'B') 2
('A', 'B', 'A') 1
('A', 'B', 'B') 1
('B', 'A', 'A') 2
('B', 'A', 'B') 1
('B', 'B', 'A') 1
('B', 'B', 'B') 0
</code></pre>

<p>We need to append <code>or [0]</code> to the list comprehension to cover the situation where no "A"s are found, otherwise <code>max</code> complains that we're trying to find the maximum of an empty sequence. </p>

<h3>Update</h3>

<p>Padraic Cunningham reminded me that the Python 3 version of <code>max</code> accepts a default arg to handle the situation when you pass it an empty iterable. He also shows another way to calculate the length of an iterable that is a bit nicer since it avoids capturing the iterable into a list, so it's a bit faster and consumes less RAM, which can be handy when working with large iterables. So we can rewrite the above code as</p>

<pre><code>from itertools import product, groupby

for t in product("AB", repeat=3):
    a = max((sum(1 for _ in g) for k, g in groupby(t) if k == "A"), default=0)
    print(t, a)
</code></pre>

python itertools