Выбор остановочного списка?
Представьте, что у меня есть список заказов кортежей:
s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)]
Учитывая параметр X
, я хочу выбрать все кортежи, у которых первый элемент равен или больше, чем X
, но не включая первый кортеж, который имеет -1 в качестве второго элемента.
Например, если X = 3
, я хочу выбрать список [(3,0), (4,0)]
Одна из моих идей:
Получить ключ отсечки с помощью
E = min (x [0] for x in s if (x [0] >= X) and (x [1] == -1) )
Затем выберите элементы с клавишами между X
и E
:
R = [x for x in s if X <= x [0] < E]
Это дает мне то, что я хочу в R, но кажется действительно неэффективным, включая два сканирования таблицы. Я мог бы сделать это в цикле for, отбрасывая кортежи с слишком маленькими ключами и break, когда я нажимаю первый блокирующий кортеж. Но для бегов, как собака, по сравнению с выбором списка.
Есть ли супер-эффективный способ python-esque (2.7)?
Ответы
Ответ 1
Вы можете просто фильтровать кортежи из списка в качестве выражения генератора, а затем вы можете прекратить принимать значения из выражения генератора, когда вы получите первый кортеж, второй элемент которого -1
, как этот
>>> s = [(0,-1), (1,0), (2,-1), (3,0), (4,0), (5,-1), (6,0), (7,-1)]
>>> from itertools import takewhile
>>> X = 3
>>> list(takewhile(lambda x: x[1] != -1, (item for item in s if item[0] >= X)))
[(3, 0), (4, 0)]
Здесь выражение-генератор (item for item in s if item[0] >= X)
будет давать значения по одному, по требованию (они не генерируются одновременно, поэтому мы сохраняем здесь память), которые больше или равны X
.
Затем мы принимаем значения из этого выражения генератора только до тех пор, пока не найдем кортеж, второй элемент которого не равен -1
, с itertools.takewhile
.
Ответ 2
Здесь немного взломано реализовать takewhile
как часть выражения генератора:
def stop(): raise StopIteration
result = (
stop() if item[1] == -1 else
item
for item in s
if item[0] >= X
)
Или с другой фразой:
def until(cond):
if cond: raise StopIteration
return True
result = (
item for item in s
if item[0] >= X
and until(item[1] == -1)
)