Ведение подсчета в понимании списка python

В Python есть ли counter во время понимания списка, как это было бы в случае цикла for?

Было бы более понятно, почему мне нужен счетчик, в этом примере:

Я хочу добиться следующего:

Начальный список: ['p', 'q', 'r', 's']

Желаемый список: [(1, 'P'), (2, 'Q'), (3, 'R'), (4, 'S')]

В нужном списке первый элемент каждого кортежа - порядковые числа. Если бы это был просто плоский список, я мог бы использовать zip для достижения этого. Но, однако, список, с которым я имею дело, является вложенным, трехуровневым (думаю, иерархические данные), и он генерируется посредством понимания списка.

Итак, мне было интересно, есть ли способ ввести эти порядковые числа во время понимания списка. Если нет, то какое наилучшее возможное решение.

P.S.: Здесь строчные буквы преобразуются в верхний регистр, но это не является частью проблемы, думайте об этом как о простом преобразовании данных.

код:

allObj = Category.objects.all()

tree =[(_, l1.name, [(__, l2.name, [(___, l3.name) for l3 in allObj if l3.parentid == l2.categoryid]) for l2 in allObj if l2.parentid == l1.categoryid]) for l1 in allObj if l1.parentid == None]

allObj содержит данные из категории таблицы, которые, в свою очередь, содержат иерархические данные, представленные в виде списка привязанностей.

Я поставил _, где мне нужны порядковые числа. Обратите внимание, что список вложен, так что на каждом уровне будет отдельный счетчик, представляемый 1, 2 и 3 _ s.

Ответ 1

Самый простой случай

[(i, x) for i, x in enumerate(some_list, 1)]

Применить фильтр с помощью if-statements

[(i, x) for i, x in enumerate(some_list, 1) if i > 2]

или как это

[(i, x) for i, x in enumerate(some_list, 1) if x != 'p']

Слово совета

Чаще всего вам не нужно это делать. Вместо этого вы просто вызываете enumerate(some_list, 1), где требуется перечисление, например, в цикле for.

Ответ 2

Как уже было показано в других ответах, стандартная библиотека дает вам enumerate, что означает, что вам, вероятно, даже не нужен список, например:

[(1, 'P'), (2, 'Q'), (3, 'R'), (4, 'S')]

потому что каждый раз, когда вам нужно связать букву с номером, связанным с его положением, вы можете просто позвонить enumerate.
Пример:

>>> low = ['p', 'q', 'r', 's']
>>> upp = [c.upper() for c in low]
>>>
>>> for i,c in enumerate(upp, 1):
...     print(i,c)
...
1 P
2 Q
3 R
4 S

Это был просто пример, возможно, вам действительно нужен этот список.

Ответ 3

RTM: enumerate(['p', 'q', 'r', 's'], 1) дает вам генератор, дающий (1, 'p'), (2, 'q'), (3, 'r'), (4, 's'), преобразовать его в list по вкусу.

Ответ 4

Я искал что-то немного другое, когда я наткнулся на этот ответ.

Мое дело состояло в том, чтобы вести подсчет, основываясь на условии внутри понимания списка. На всякий случай это полезно кому-то другому, вот как я его решил:

import itertools counter = itertools.count(0) [(next(counter), x) for x in some_list if x != 'p']

Таким образом, счетчик будет увеличиваться только при выполнении условия, а не на каждой итерации.

Ответ 5

L = ['p', 'q', 'r', 's']
[(i + 1, x) for i, x in enumerate(L)]

Ответ 6

Помогло бы что-то подобное?

i = 1

y = range(10)

s = [(i + y.index(x), x**2) for x in y]

print s

>>> [(1, 0), (2, 1), (3, 4), (4, 9), (5, 16), (6, 25), (7, 36), (8, 49), (9, 64), (10, 81)]

У меня есть подозрение, что может быть лучший способ сделать это, чем через понимание.

Ответ 7

Я думаю, вы хотите что-то вроде нумерации всех предметов, независимо от уровня гнездования. Может быть, следующее поможет. Не забудьте создать новый number для каждого понимания списка. next может быть записано __next__ в вашей версии Python.

>>> import itertools
>>> number = itertools.count().next
>>> [(number(), [(number(), x + 1) for x in range(y) if x % 2]) for y in range(10) if y % 3]
[(0, []), (1, [(2, 2)]), (3, [(4, 2), (5, 4)]), (6, [(7, 2), (8, 4)]), (9, [(10, 2), (11, 4), (12, 6)]), (13, [(14, 2), (15, 4), (16, 6), (17, 8)])]

Update: Я знаю, что вам нужно разные счетчики для каждого уровня гнездования. Просто используйте более одного счетчика:

>>> number1 = itertools.count().__next__
>>> number2 = itertools.count().__next__
>>> print([(number1(), [(number2(), x + 1) for x in range(y) if x % 2]) for y in range(10) if y % 3])
[(0, []), (1, [(0, 2)]), (2, [(1, 2), (2, 4)]), (3, [(3, 2), (4, 4)]), (4, [(5, 2), (6, 4), (7, 6)]), (5, [(8, 2), (9, 4), (10, 6), (11, 8)])]

I.e., замените _ на number1(), как определено выше, __ с number2() и т.д. Это.