Я хотел бы знать лучший способ (более компактный и "питонический" способ) сделать специальную обработку для последнего элемента в цикле for. Существует фрагмент кода, который следует вызывать только между элементами, подавляя в последнем.
Вот как я сейчас это делаю:
for i, data in enumerate(data_list):
code_that_is_done_for_every_element
if i != len(data_list) - 1:
code_that_is_done_between_elements
Есть ли лучший способ?
Примечание: я не хочу делать это с помощью таких хаков, как использование reduce
.;)
Ответы:
В большинстве случаев проще (и дешевле) сделать первую итерацию особой, а не последнюю:
Это будет работать для любого повторяемого, даже для тех, которые не имеют
len()
:Кроме того, я не думаю, что есть вообще превосходное решение, поскольку оно зависит от того, что вы пытаетесь сделать. Например, если вы строите строку из списка, естественно, ее лучше использовать,
str.join()
чем использоватьfor
цикл «с особым случаем».Используя тот же принцип, но более компактный:
Выглядит знакомо, не правда ли? :)
Для @ofko и других, которым действительно необходимо выяснить, является ли текущее значение итерируемого без
len()
последнего, вам нужно смотреть в будущее:Тогда вы можете использовать это так:
источник
if
которого можно было бы избежать, если бы цикл был разбит на два цикла. Однако это актуально только при итерации огромного списка данных.next()
. Затем я использую тот факт, что итератор сам по себе итеративен, поэтому я могу использовать его вfor
цикле до исчерпания, итерации от второго до последнего значения. В течение этого времени я сохраняю текущее значение, полученное от итератора, иyield
последнее. Таким образом, я знаю, что есть еще одна ценность. После цикла for я сообщал о каждом значении, кроме последнего.Хотя этот вопрос довольно старый, я пришел сюда через Google и нашел довольно простой способ: нарезка списка. Допустим, вы хотите поставить '&' между всеми записями списка.
Это возвращает «1 & 2 & 3».
источник
len(l)=1000000
в этом примере программа будет работать некоторое время.append
рекомендуется афаик.l=[1,2,3]; l.append(4);
«Код между» является примером шаблона « голова-хвост» .
У вас есть предмет, за которым следует последовательность пар (между предметами). Вы также можете просмотреть это как последовательность пар (элемент, между), за которыми следует элемент. Обычно проще воспринимать первый элемент как особый, а все остальные - как «стандартный» случай.
Кроме того, чтобы избежать повторения кода, вы должны предоставить функцию или другой объект, содержащий код, который вы не хотите повторять. Внедрение оператора if в цикл, который всегда ложен, за исключением одного раза, немного глупо.
Это более надежно, потому что его немного легче доказать. Он не создает дополнительной структуры данных (то есть копии списка) и не требует много потерянного выполнения условия if, которое всегда ложно, за исключением одного раза.
источник
if
операторы, поэтому аргумент «потраченное впустую исполнение» не выполняется.if
секунд». Очевидно, вы просто ссылаетесь на «чистоту кода»?if
утверждения действительно более чистым в сообществе Python?Если вы просто хотите изменить последний элемент,
data_list
вы можете просто использовать обозначение:Тем не менее, похоже, что вы делаете больше, чем это. В твоем пути нет ничего плохого. Я даже бросил быстрый взгляд на некоторый код Django для их тегов шаблонов, и они в основном делают то, что вы делаете.
источник
if data != datalist[-1]:
мой взгляд, изменение выражения if на: и сохранение всего остального было бы наилучшим способом кодирования.если предметы уникальны:
другие варианты:
источник
Это похоже на подход Антса Аасмы, но без использования модуля itertools. Это также запаздывающий итератор, который просматривает один элемент в потоке итератора:
источник
Вы можете использовать скользящее окно поверх входных данных, чтобы просмотреть следующее значение и использовать часовой для определения последнего значения. Это работает для любой итерации, поэтому вам не нужно заранее знать длину. Парная реализация взята из рецептов itertools .
источник
Нет ли возможности перебрать все элементы, кроме последнего, и обработать последний вне цикла? В конце концов, создается цикл, который делает что-то похожее на все элементы, над которыми вы зацикливаетесь; если одному элементу нужно что-то особенное, оно не должно быть в цикле.
(см. также этот вопрос: « делает ли последний элемент в цикле достойный отдельного обращения» )
РЕДАКТИРОВАТЬ: так как вопрос больше о «между», либо первый элемент является особенным в том, что он не имеет предшественника, или последний элемент является особенным в том, что он не имеет преемника.
источник
Мне нравится подход @ ethan-t, но
while True
он опасен с моей точки зрения.Здесь
data_list
так, что последний элемент по значению равен первому из списка. L может быть заменен на,data_list
но в этом случае он будет пустым после цикла.while True
также возможно использовать, если вы проверяете, что список не пуст перед обработкой или проверка не нужна (ой!).Хорошая часть в том, что это быстро. Плохое - это разрушаемо (
data_list
становится пустым).Наиболее интуитивное решение:
Ах, да, вы уже предложили это!
источник
В вашем пути нет ничего плохого, если у вас не будет 100 000 циклов и вы хотите сохранить 100 000 операторов if. В этом случае вы можете пойти по этому пути:
Выходы:
Но на самом деле, в вашем случае я чувствую, что это излишне.
В любом случае вам наверняка повезет с нарезкой:
или просто :
В конце концов, KISS способ сделать что-то, и это будет работать с любой итерацией, в том числе без
__len__
:Выходы:
Если мне кажется, что я бы так поступил, мне кажется, это просто.
источник
item
вместо пересчета его с помощьюlist[-1]
. Но тем не менее: я не думаю, что это то, о чем просил ФП, не так ли?iterable.__iter__()
- пожалуйста, не вызывайте__
функции напрямую. Должно бытьiter(iterable)
.Используйте нарезку и,
is
чтобы проверить последний элемент:Caveat emptor : Это работает только в том случае, если все элементы в списке на самом деле разные (имеют разные места в памяти). Под капотом Python может обнаружить одинаковые элементы и использовать для них одни и те же объекты. Например, для строк с одинаковым значением и общими целыми числами.
источник
если вы просматриваете список, для меня это тоже сработало:
источник
Google привел меня к этому старому вопросу, и я думаю, что мог бы добавить другой подход к этой проблеме.
Большинство ответов здесь будут касаться правильной обработки элемента управления цикла for, как его просили, но если data_list разрушаем, я бы посоветовал вам выталкивать элементы из списка до тех пор, пока вы не получите пустой список:
вы можете даже использовать while len (element_list), если вам не нужно ничего делать с последним элементом. Я считаю это решение более элегантным, чем работа с next ().
источник
Для меня самый простой и питонный способ обработки особого случая в конце списка:
Конечно, это также может быть использовано для особой обработки первого элемента.
источник
Вместо того, чтобы считать, вы также можете считать:
источник
Задержка специальной обработки последнего элемента до окончания цикла.
источник
Там может быть несколько способов. нарезка будет самой быстрой. Добавляем еще один, который использует метод .index ():
источник
Предполагая ввод в качестве итератора, вот способ использования tee и izip из itertools:
Демо-версия:
источник
Самое простое решение, которое приходит мне в голову:
Поэтому мы всегда смотрим в будущее на один пункт, задерживая выполнение одной итерации. Чтобы пропустить что-то во время первой итерации, я просто улавливаю ошибку.
Конечно, вам нужно немного подумать,
NameError
чтобы поднять, когда вы этого хотите.Также держите `Сундук`
Это полагает, что имя new ранее не было определено. Если вы параноик, вы можете убедиться, что
new
его не существует, используя:В качестве альтернативы вы также можете использовать оператор if (
if notfirst: print(new) else: notfirst = True
). Но, насколько я знаю, накладные расходы больше.поэтому я ожидаю, что накладные расходы не будут выбраны.
источник
Подсчитайте предметы один раз и следите за количеством оставшихся предметов:
Таким образом, вы оцените длину списка только один раз. Многие из решений на этой странице, кажется, предполагают, что длина заранее недоступна, но это не часть вашего вопроса. Если у вас есть длина, используйте ее.
источник
На ум приходит одно простое решение:
Второе столь же простое решение может быть достигнуто с помощью счетчика:
источник