Упростить генератор
Есть экземпляр класса, который принимает несколько значений. Из них меняются только два - 'a', 'b'. Причём, 'a' меняется каждый раз, а 'b' меняется только дважды.
Я хочу сделать так, чтобы список этих экземпляров генерировался на лету.
'a' - это координата. Значения убывают с шагом '-10'. То есть используется range(640, 420, -10)
'b' - это стейт. Значения бывают самое первое - 'PRESSED', потом следуют много 'MOVE', в конце 'RELEASED'.
Нужно сгенерировать список вида
[A(640, 'PRESSED'),
A(630, 'MOVE'),
A(620, 'MOVE'),
...
A(450, 'MOVE'),
A(440, 'MOVE'),
A(430, 'RELEASED')]
Простая арифметика даёт нам понять, что элементов будет 22. На данный момент я делаю генератор списка координат, а дальше циклом с вложенным оператором if я создаю список этих экземпляров:
На данный момент я всё делаю так:
exmp = []
coordinates = [i for i in range(640, 420, -10)]
for coordinate in coordinates:
if coordinates.index(coordinate) == 0:
exmp.append(A(coordinate, 'PRESSED'))
elif coordinates.index(coordinate) == 21:
exmp.append(A(coordinate, 'RELEASED'))
else:
exmp.append(A(coordinate, 'MOVE'))
Но код страшно не нравится. Можно ли его как-то упростить? Необходимо получить этот вот список exmp каким-то более читаемым и простым способом и без привязки к индексам, как использовано в if-ах. Чтобы оно просто брало первый элемент, впихивало в него первую (само понимало, что координата первая) координату из генератора и ставило стейт 'PRESSED', потом вторую координату, ставило стейт 'MOVE', третью, и в самом конце брало последнюю (само понимало, что это последняя координата) координату и ставило стейт 'RELEASED'.
Ответы (3 шт):
Либо взять код из комментария EzikBro, либо можно так (смесь двух кодов):
exmp = []
coordinates = range(640, 420, -10)
exmp.append(A(coordinates[0], 'PRESSED'))
for coordinate in coordinates[1:-1]:
exmp.append(A(coordinate, 'MOVE'))
exmp.append(A(coordinates[-1], 'RELEASED'))
A = tuple # Demo
start = 640; stop = 430; step = -10
assert start > stop
qty = int((start - stop) / abs(step)) + 1
coors = range(start, stop - 1, step)
state = ['PRESSED'] + ['MOVE'] * (qty - 2) + ['RELEASED']
exmp = list(map(A, zip(coors, state)))
print(exmp)
Но можно запихать и в одну строчку, если занимаемся спортивным сокращением кода)
exmp = list(map(A, zip(range(640, 420, -10), ['PRESSED'] + ['MOVE'] * 20 + ['RELEASED'])))
start = 640
stop = 420
step = -10
sequence = [
('PRESSED' if i == 0 else 'RELEASED' if x == stop - step else 'MOVED', x)
for (i, x) in enumerate(range(start, stop, step))]
Как вариант, вместо нестабильного x == stop - step, которое сломается, если stop-start не кратно step, можно посчитать последний индекс: i == (stop-start)//step-1