Двоичная строка для перечисления Python

#python #list #binary

Вопрос:

У меня есть двоичная строка типа '1100011101' . Я хотел бы проанализировать его в виде списка, где каждый фрагмент 1 или 0 является отдельным значением в списке.

Такие как: '1100011101' становится ['11', '000', '111', '0', '1']

Ответ №1:

Вы можете извлечь из этого (незначительную) часть производительности, используя регулярное выражение вместо groupby() join() . Это просто находит группы 1 или 0 :

 import re

s = '1100011101'
l = re.findall(r"0 |1 ", s)
# ['11', '000', '111', '0', '1']
 

Тайминги:

 s = '1100011101' * 1000

%timeit l = [''.join(g) for _, g in groupby(s)]
# 1.16 ms ± 9.79 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit re.findall(r"0 |1 ", s)
# 723 µs ± 5.32 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
 

Ответ №2:

Воспользуйся itertools.groupby :

 from itertools import groupby

binary = "1100011101"

result = ["".join(repeat) for _, repeat in groupby(binary)]
print(result)
 

Выход

 ['11', '000', '111', '0', '1']
 

Ответ №3:

Вставьте пробел между переходами 01 и 10 с помощью .replace (), а затем разделите полученную строку:

 '1100011101'.replace("01","0 1").replace("10","1 0").split()

['11', '000', '111', '0', '1']
 

Ответ №4:

с groupby

 >>> from itertools import groupby as f
>>> x = str(1100011101)
>>> sol = [''.join(v) for k, v in f(x)]
>>> print(sol)
['11', '000', '111', '0', '1']
 

без использования groupby и если вы хотите более быстрого выполнения

 def func(string):
    if not string:
        return []
    def get_data(string):
            if not string:
                return 
            count = 0
            target = string[0]
            for i in string:
                if i==target:
                    count =1
                else:
                    yield target*count
                    count = 1
                    target = i
            if count>0:
                yield target*count
    return list(get_data(string))
        
    x = '1100011101'
    sol =func(x)
    print(sol)
 

выход

 ['11', '000', '111', '0', '1']
 

Тайминги на моей машине

  from itertools import groupby

s = '11000111010101' * 100000

%timeit l = [''.join(g) for _, g in groupby(s)]
318 ms ± 2.75 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


import re

s = '11000111010101' * 100000

%timeit l = re.findall(r"0 |1 ", s)
216 ms ± 2.01 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


def func(string):
    if not string:
        return []
    def get_data(string):
            if not string:
                return 
            count = 0
            target = string[0]
            for i in string:
                if i==target:
                    count =1
                else:
                    yield target*count
                    count = 1
                    target = i
            if count>0:
                yield target*count
    return list(get_data(string))

s = '11000111010101' * 100000

%timeit func(s)
205 ms ± 11.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
####################################################################

from itertools import groupby

s = '11000111010101' * 1000

%timeit l = [''.join(g) for _, g in groupby(s)]
3.28 ms ± 178 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


import re

s = '11000111010101' * 1000

%timeit l = re.findall(r"0 |1 ", s)
2.06 ms ± 57.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


def func(string):
    if not string:
        return []
    def get_data(string):
            if not string:
                return 
            count = 0
            target = string[0]
            for i in string:
                if i==target:
                    count =1
                else:
                    yield target*count
                    count = 1
                    target = i
            if count>0:
                yield target*count
    return list(get_data(string))

s = '11000111010101' * 1000

%timeit func(s)
1.91 ms ± 153 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)