Подумайте о 0 как false и 1 как истина. Затем побитовые и (& amp;) и / или (|) работают так же, как и обычные, и / или только за исключением того, что все биты в значении сразу. Как правило, вы увидите, что они используются для флагов, если у вас есть 30 параметров, которые можно установить (например, стили рисования в окне), которые вы не хотите передавать в 30 отдельных логических значениях, чтобы установить или отключить их, чтобы вы использовали | для объединения опций в одно значение, а затем вы используете & amp; чтобы проверить, установлена ли каждая опция. Этот стиль прохождения флага сильно используется OpenGL. Поскольку каждый бит является отдельным флагом, вы получаете значения флага по степеням двух (или числа, которые имеют только один бит) 1 (2 ^ 0) 2 (2 ^ 1) 4 (2 ^ 2) 8 (2 ^ 3) мощность двух указывает, какой бит установлен, если флаг включен.
Также обратите внимание на 2 = 10, так что x | 2 равно 110 (6) не 111 (7) Если ни один из битов не перекрывается (что true в этом случае) | действует как дополнение.
Если вы действительно хотите использовать регулярные выражения, вы можете изменить списки целых чисел на строки и использовать это регулярное выражение
import re
def find_span(numbers, start, end):
# Create strings from the start and end lists.
start_pattern = ''.join(map(chr, start))
end_pattern = ''.join(map(chr, end))
# convert the list to search into one string.
s = ''.join(map(chr, numbers))
# Create a pattern that starts and ends with the correct sublists,
# and match all sublists. Then convert each match back to a list of
# integers
# The '?' is to make the regex non-greedy
return [
[ord(c) for c in match]
for match in re.findall(rf'{start_pattern}.*?{end_pattern}', s, re.DOTALL)
]
>>> find_span(search, start, end) # Using OP's sample values
[[1, 2, 3, 99, 99, 99, 4, 5, 6], [1, 2, 3, 99, 4, 5, 6]]
Обратите внимание, что это не очень эффективно, поскольку для этого требуется динамическое построение regex каждый раз, когда он вызывается. И вам нужно использовать re.DOTALL
, потому что иначе он не будет соответствовать ничему, содержащему 10
(который является ascii-кодировкой новой строки). Однако, если вы действительно хотите использовать регулярные выражения , это сработает.
Вот подход itertools, который использует ограниченную длину collections.deque
, чтобы сохранить буфер последних элементов соответствующего размера. Предполагается, что ваши подсписки не перекрываются и что ваши начальные и конечные последовательности не перекрываются.
Он работает для любой последовательности для данных, начала, конца (даже генераторы).
from collections import deque
from itertools import islice
def sublists(data, start, end):
it = iter(data)
start, end = deque(start), deque(end)
while True:
x = deque(islice(it, len(start)), len(start))
# move forward until start is found
while x != start:
x.append(next(it))
out = list(x)
x = deque(islice(it, len(end)), len(end))
# move forward until end is found, storing the sublist
while x != end:
out.append(x[0])
x.append(next(it))
out.extend(end)
yield out
data = [99, 99, 1, 2, 3, 99, 99, 99, 4, 5, 6, 99, 99, 1, 2, 3, 99, 4, 5, 6, 99]
startSequence = [1,2,3]
endSequence = [4,5,6]
print(list(sublists(data, startSequence, endSequence)))
# [[1, 2, 3, 99, 99, 99, 4, 5, 6], [1, 2, 3, 99, 4, 5, 6]]
Вот более общее решение, которое не требует, чтобы списки были sliceable, поэтому вы можете использовать его на других итерациях, например, генераторах.
Мы сохраняем deque
размер start
пока мы не встретим его. Затем мы добавляем эти значения в список и продолжаем повторять последовательность. Как и мы, мы сохраняем deque
размер конечной последовательности, пока не увидим ее, а также добавим элементы в список, который мы сохраняем. Если мы сталкиваемся с конечной последовательностью, мы yield
, которые перечислили и установили deque
для сканирования следующей стартовой последовательности.
from collections import deque
def gen(l, start, stop):
start_deque = deque(start)
end_deque = deque(stop)
curr_deque = deque(maxlen=len(start))
it = iter(l)
for c in it:
curr_deque.append(c)
if curr_deque == start_deque:
potential = list(curr_deque)
curr_deque = deque(maxlen=len(stop))
for c in it:
potential.append(c)
curr_deque.append(c)
if curr_deque == end_deque:
yield potential
curr_deque = deque(maxlen=len(start))
break
print(list(gen([99, 99, 1, 2, 3, 99, 99, 99, 4, 5, 6, 99, 99, 1, 2, 3, 99, 4, 5, 6, 99], [1,2,3], [4,5,6])))
# [[1, 2, 3, 99, 99, 99, 4, 5, 6], [1, 2, 3, 99, 4, 5, 6]]
Используйте метод ниже:
def find_sub_list(sl,l):
sll=len(sl)
for ind in (i for i,e in enumerate(l) if e==sl[0]):
if l[ind:ind+sll]==sl:
return ind,ind+sll-1
find_sub_list([1,2,3], data)
>>>(2, 4)
find_sub_list([4,5,6], data)
>>>(8, 10)
data[2:10+1]
>>>[1, 2, 3, 99, 99, 99, 4, 5, 6]
Вы можете использовать аналогичный подход для sublists[1]
Предоставлено: find-start-and-end-index-of- подсписок-в-списке
Здесь находится решение O (n), которое находит совпадения, отслеживая соответствие шаблонов startSequence и endSequence
def myFunctionForSublists(data, startSequence, endSequence):
start,end = tuple(startSequence), tuple(endSequence)
l1, l2 = len(start), len(end)
s = -1
result = []
for i,v in enumerate(zip(*[data[i:] for i in range(0,l1)])):
if v == start:
s = i
if v == end and s != -1:
result.append(data[s:i+l2])
s = -1
return result
print (myFunctionForSublists(data, startSequence, endSequence))
# [[1, 2, 3, 99, 99, 99, 4, 5, 6], [1, 2, 3, 99, 4, 5, 6]]
Просто переберите все в индексы в списке и сравните срез с startSequence
или endSequence
, соответственно. Предполагая, что подписи не должны перекрываться, вы можете использовать один и тот же итератор для обоих циклов.
def myFunctionForSublists(data, startSequence, endSequence):
positions = iter(range(len(data)))
for start in positions:
if data[start:start+len(startSequence)] == startSequence:
for end in positions:
if data[end:end+len(endSequence)] == endSequence:
yield data[start:end+len(endSequence)]
break
Таким образом, цикл start
будет продолжаться, когда петля end
будет оставаться. Если они могут перекрывать , используйте два отдельных итератора для цикла, то есть for start in range(len(data)):
и for end in range(start+1, len(data)):