У меня есть список l =[253, 59, 2, 0, 0, 0, 0, 0], и я хочу установить диапазон (0, 255) для каждого элемента в списке. Я хочу реализовать это на питоне. Я хочу увеличивать элементы один за другим, так что, когда он достигает максимального диапазона, элемент должен сбрасываться на 0, а следующий элемент должен увеличиваться на 1
Вывод должен выглядеть так после каждой итерации:
l =[253, 59, 2, 0, 0, 0, 0, 0]
l =[254, 59, 2, 0, 0, 0, 0, 0]
l =[255, 59, 2, 0, 0, 0, 0, 0]
l =[0, 60, 2, 0, 0, 0, 0, 0]
l =[1, 60, 2, 0, 0, 0, 0, 0]
.
.
.
.
l =[255, 60, 2, 0, 0, 0, 0, 0]
l =[0, 61, 2, 0, 0, 0, 0, 0]
Я хочу знать, есть ли способ сделать это с помощью numpy lib. так как с числовыми массивами работать быстрее, чем со списками. @mozway
поскольку вам нужно будет повторять, я сомневаюсь, что numpy сильно поможет, можете ли вы сообщить нам, должен ли ввод быть произвольным? например если l = [255, 255, 255, 7, 0], то следующая итерация должна быть [0, 0, 0, 8, 0]?
да ввод должен быть произвольным.






Один вариант в чистом питоне:
l = [253, 59, 2, 0, 0, 0, 0, 0]
pos = 0
n_iter = 10
step = 0
for step in range(n_iter):
for pos in range(len(l)):
if l[pos] < 255:
l[pos] += 1
break
else:
l[pos] = 0
print(f'step {step+1}: {l}')
Вывод:
step 1: [254, 59, 2, 0, 0, 0, 0, 0]
step 2: [255, 59, 2, 0, 0, 0, 0, 0]
step 3: [0, 60, 2, 0, 0, 0, 0, 0]
step 4: [1, 60, 2, 0, 0, 0, 0, 0]
step 5: [2, 60, 2, 0, 0, 0, 0, 0]
step 6: [3, 60, 2, 0, 0, 0, 0, 0]
step 7: [4, 60, 2, 0, 0, 0, 0, 0]
step 8: [5, 60, 2, 0, 0, 0, 0, 0]
step 9: [6, 60, 2, 0, 0, 0, 0, 0]
step 10: [7, 60, 2, 0, 0, 0, 0, 0]
с петлей,
array = [253, 59, 2, 0, 0, 0, 0, 0]
index = 0
while index < len(array):
while array[index]<256:
array[index] += 1
print(array)
array[index] = 0
index += 1
Один из способов с циклом:
def inc_list(l):
for i in range(len(l)):
l[i] += 1
if l[i] > 255:
l[i] = 0
else:
return
for _ in range(300):
print(l)
inc_list(l)
В качестве альтернативы рекурсивное решение:
def inc_list(l):
if not l:
return []
elif l[0] == 255:
return [0] + inc_list(l[1:])
else:
return [l[0] + 1] + l[1:]
for _ in range(300):
print(l)
l = inc_list(l)
tl;dr: однострочник
import struct
list(struct.pack('<Q', struct.unpack('<Q', bytes(start))[0]+1))
Просто чтобы представить другое представление, это то, что вы, кажется, считаете в списке из 8 байтов, представляющих 64-битное целое число с прямым порядком байтов... Почему бы вам просто не сделать это?
def plusOne(l):
n=0
b=1
for dg in l:
n+=b*dg
b*=256
n+=1
res=[]
for i in range(len(l)):
res.append(n%256)
n//=256
return res
Как есть, этот ответ не быстрее, чем другие. Я предполагаю, что это даже медленнее (не успел. Но, ну, это явно сложнее).
Но если то, что вы хотите иметь, это просто счетчик, вы можете упростить, сохранив только целое число в качестве значения состояния и сгенерировав список
def listCounter(start, size):
while True:
res=[]
x=start
for i in range(size):
res.append(x%256)
x//=256
yield res
start+=1
myiter=listCounter(254, 8)
print(next(myiter))
print(next(myiter))
for _,l in zip(range(20),listCounter(510,8)):
print(l)
Поскольку именно так 8-байтовое целое число подсчитывается на оборудовании, вы даже можете полагаться на процессор, чтобы сделать это, а не пытаться имитировать его в python.
import struct
l=[254, 255, 0, 0, 1, 0, 0, 0]
nextl=list(struct.pack('<Q', struct.unpack('<Q', bytes(l))[0]+1))
Или в for итератора
import struct
def listCounter(start):
while True:
yield start
start=list(struct.pack('<Q', struct.unpack('<Q', bytes(start))[0]+1))
for _,l in zip(range(10), listCounter([254,255,0,0,1,0,0,0])):
print(l)
[254, 255, 0, 0, 1, 0, 0, 0]
[255, 255, 0, 0, 1, 0, 0, 0]
[0, 0, 1, 0, 1, 0, 0, 0]
[1, 0, 1, 0, 1, 0, 0, 0]
[2, 0, 1, 0, 1, 0, 0, 0]
[3, 0, 1, 0, 1, 0, 0, 0]
[4, 0, 1, 0, 1, 0, 0, 0]
[5, 0, 1, 0, 1, 0, 0, 0]
[6, 0, 1, 0, 1, 0, 0, 0]
[7, 0, 1, 0, 1, 0, 0, 0]
bytes(l) — это массив байтов, содержащий 8 байтов в lbytes(l) -> b'\xfe\xff\x00\x00\x01\x00\x00\x00'
Эти 8 байтов представляют собой 64-битное представление числа. Который мы можем извлечь с помощью struct.unpack, указав формат <Q (64-битное целое число, обратный порядок байтов, сначала увеличиваются первые байты)struct.unpack('<Q', bytes(l)) → (4295032830,)
Это форма кортежа, потому что мы могли запросить последовательность разных чисел. Итакstruct.unpack('<Q', bytes(l))[0] → 4295032830
Мы можем увеличить егоstruct.unpack('<Q', bytes(l))[0]+1 → 4295032831
И мы можем получить 64-битное представление массива байтов этого нового целого числа, используя packstruct.pack('<Q',struct.unpack('<Q', bytes(l))[0]+1) → b'\xff\xff\x00\x00\x01\x00\x00\x00'
Этот массив байтов представляет собой просто числа от 0 до 255, мы можем легко получить их, преобразовав его в списокlist(struct.pack('<Q',struct.unpack('<Q', bytes(l))[0]+1)) → [255, 255, 0, 0, 1, 0, 0, 0]
Задача эквивалентна поиску представлений последовательных целых чисел в позиционной системе счисления с основанием 256 (но вы также можете использовать смешанные основания).
numpy распутывать и распутыватьДля меньших списков вы можете найти целое число, имеющее вид l = [253, 59, 2, 0]
value = np.ravel_multi_index(l, [256] * 4, order='F') #sets value to 146429
А затем используйте np.unravel_index, чтобы получить представления первых, скажем, 5 целых чисел:
np.transpose(np.unravel_index(np.arange(value, value+5), [256]*4, order='F'))
>>> array([[253, 59, 2, 0],
[254, 59, 2, 0],
[255, 59, 2, 0],
[ 0, 60, 2, 0],
[ 1, 60, 2, 0]], dtype=int64)
В вашем случае требуется размер = [256] * 8. Это слишком велико, потому что целые числа не могут превышать 2**63 в numpy, а ValueError будет выброшено. В этом случае вы можете реализовать свой собственный способ замены np.ravel_multi_index и np.unravel_index:
shape = np.cumprod([1, 256, 256, 256, 256, 256, 256, 256], dtype=np.int64)
value = np.dot(l, shape) #same 146429
def unravel(values, shape=[256] * 8):
steps = len(values)
result_arr = np.empty(shape=(len(shape), steps), dtype=int)
for j in range(len(shape)):
result_arr[j] = values % shape[j]
values = values // shape[j]
return np.transpose(result_arr)
unravel(np.arange(value, value+5))
>>> array([[253, 59, 2, 0, 0, 0, 0, 0],
[254, 59, 2, 0, 0, 0, 0, 0],
[255, 59, 2, 0, 0, 0, 0, 0],
[ 0, 60, 2, 0, 0, 0, 0, 0],
[ 1, 60, 2, 0, 0, 0, 0, 0]])
Обратите внимание, что во всех случаях требуется только 8 итераций, поэтому он должен быть быстрее, чем только пути Python.
«Я хочу реализовать это на питоне», тогда почему вы отметили это
numpy?