How to maintain a strict alternating pattern of types elements in a list?

Given a list of lines, where each line is in the format "A-something" or "B-somethingelse", and the list items are mainly alternated between pieces of data "A" and "B", how can the violations be removed?

  • Unevenness is any sequence that breaks pattern A B.
  • If there are several A, you should also delete the next B.
  • If there are multiple Bs, the previous A must also be deleted.
  • After removing these invalid sequnces, the list order should be kept.

Example: ABAB AAB ABABAB ABB ABAB AABB ABAB

In this case, AAB (see rule 2), ABB (see rule 3) and AABB should be deleted.

+4
source share
4 answers

I will give it a try with regexp returning indexes of sequences to be deleted

>>> import re
>>> data = 'ABABAABABABABABBABABAABBABAB'
>>> [(m.start(0), m.end(0)) for m in re.finditer('(AA+B+)|(ABB+)', data)]
[(4, 7), (13, 16), (20, 24)]

or stripping result

>>> re.sub('(AA+B+)|(ABB+)', '', data)
ABABABABABABABABAB
+3
source

Solution for drunk on itertools:

>>> s = 'ABABAABABABABABBABABAABBABAB'
>>> from itertools import groupby, takewhile, islice, repeat, chain
>>> groups = (list(g) for k,g in groupby(s))
>>> pairs = takewhile(bool, (list(islice(groups, 2)) for _ in repeat(None)))
>>> kept_pairs = (p for p in pairs if len(p[0]) == len(p[1]) == 1)
>>> final = list(chain(*chain(*kept_pairs)))
>>> final
['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B', 'A', 'B']

(Unfortunately, I'm not in shape right now to think about corner cases and in the end A, etc.)

+2
source

. :

  • ,
  • B,
  • 1 A 1 B, ; .

, , A.

+1

itertools.groupby:

from itertools import groupby

def solve(strs):
    drop_next = False
    ans = []
    for k, g in groupby(strs):
        lis = list(g)
        if drop_next:
            #if True then don't append the current set to `ans`
            drop_next = False
        elif len(lis) > 1 and k == 'A':
            #if current group contains more than 1 'A' then skip the next set of 'B'
            drop_next = True
        elif len(lis) > 1 and k == 'B':
            #if current group contains more than 1 'B' then pop the last appended item
            if ans:
                ans.pop(-1)
        else:
            ans.append(k)
    return ''.join(ans)

strs = 'ABABAABABABABABBABABAABBABAB'
print solve(strs)
#ABABABABABABABABAB
+1

All Articles