Поддерживать счет в понимании списка Python - PullRequest
14 голосов
/ 08 февраля 2012

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

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

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

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

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

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

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

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

Код:

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 _ с.

Ответы [ 8 ]

48 голосов
/ 08 февраля 2012

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

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

Применение фильтра с операторами if

[(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.

7 голосов
/ 07 сентября 2017

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

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

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

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

4 голосов
/ 08 февраля 2012

Как уже было показано в других ответах, стандартная библиотека дает вам 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

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

1 голос
/ 08 февраля 2012

Полагаю, вы хотите что-то вроде нумерации всех элементов, независимо от уровня вложенности.Может быть, следующее поможет.Не забудьте создать новый 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)])]

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

>>> 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)])]

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

1 голос
/ 08 февраля 2012

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

0 голосов
/ 02 октября 2018

Отличная тема!Утвержденный ответ и последующие дополнения дали мне идею, которая, я думаю, может кому-то помочь.Итак, вот оно.

[print('{}. Key: {}, Value: {}'.format(i, k, v)) for i, (k, v) in enumerate(some_list.items(), 1)]

Выше можно использовать, чтобы получить симпатичный вывод словаря.Вы можете использовать его для отладки, ведения журнала и т. Д. О, да, еще одна возможность, создать CSV-файл, чтобы ваш менеджер мог открыть его в Excel.Менеджеры любят свои таблицы.

Пример вывода:

1. Key: AwesomeKey1, Value: AwesomeValue1
2. Key: AwesomeKey2, Value: AwesomeValue2
3. Key: AwesomeKey3, Value: AwesomeValue3
4. Key: AwesomeKey4, Value: AwesomeValue4
5. Key: AwesomeKey5, Value: AwesomeValue5
0 голосов
/ 08 февраля 2012

Хотелось бы что-нибудь подобное?

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)]

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

0 голосов
/ 08 февраля 2012
L = ['p', 'q', 'r', 's']
[(i + 1, x) for i, x in enumerate(L)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...