Python Итерация по списку с использованием другого списка - PullRequest
1 голос
/ 18 июня 2020

Я думаю, это просто, но со мной это не работает. У меня есть 2 списка:

a = [1, 3, 6]
b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
     ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
     ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]

, и мне нужно перебрать b, используя элементы a.

Желаемый результат:

c = [['B', 'D', 'G'],
     ['I', 'K', 'N'],
     ['P', 'R', 'U']]

Массивы приветствуются, любые предложения?

Ответы [ 4 ]

2 голосов
/ 18 июня 2020

Вы можете использовать метод itemgetter() из встроенного модуля operator:

from operator import itemgetter

a = itemgetter(1, 3, 6)

b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
     ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
     ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]

c = [list(a(l)) for l in b]

print(c)

Вывод:

[['B', 'D', 'G'],
 ['I', 'K', 'N'],
 ['P', 'R', 'U']]
1 голос
/ 18 июня 2020

(Предполагается, что ожидаемый результат содержит только опечатку.)

Самый эффективный способ generi c - через operator.itemgetter().

from operator import itemgetter


a = [1, 3, 6]

b = [['A', 'B', 'C', 'D', 'E', 'F', 'G'],
     ['H', 'I', 'J', 'K', 'L', 'M', 'N'],
     ['O', 'P', 'Q', 'R', 'S', 'T', 'U']]

c = [list(itemgetter(*a)(x)) for x in b]
print(c)
# [['B', 'D', 'G'], ['I', 'K', 'N'], ['P', 'R', 'U']]

Для ваших размеров ввода преобразование в list фактически соответствует пониманию двойного списка в моей системе, но в остальном оно происходит быстрее. Для больших a размеров NumPy становится фактически самым быстрым (хотя для этого требуется, чтобы внутренние списки b имели такое же количество элементов, что itemgetter не заботится).

Некоторые тайминги, взятые из моей тестовой системы:

%timeit [[x[i] for i in a] for x in b]
# 1000000 loops, best of 3: 1.14 µs per loop
%timeit [list(itemgetter(*a)(x)) for x in b]
# 1000000 loops, best of 3: 1.13 ns per loop
%timeit [itemgetter(*a)(x) for x in b]
# 1000000 loops, best of 3: 732 ns per loop
%timeit np.array(b)[:, tuple(a)]
# 100000 loops, best of 3: 6.84 µs per loop

b = b * 1000000
%timeit [[x[i] for i in a] for x in b]
# 1 loop, best of 3: 1.19 s per loop
%timeit [list(itemgetter(*a)(x)) for x in b]
# 1 loop, best of 3: 1.15 s per loop
%timeit [itemgetter(*a)(x) for x in b]
# 1 loop, best of 3: 800 ms per loop
%timeit np.array(b)[:, tuple(a)]
# 1 loop, best of 3: 2.31 s per loop

a = a * 100
b = b * 10000
%timeit [[x[i] for i in a] for x in b]
# 1 loop, best of 3: 386 ms per loop
%timeit [list(itemgetter(*a)(x)) for x in b]
# 10 loops, best of 3: 193 ms per loop
%timeit [itemgetter(*a)(x) for x in b]
# 10 loops, best of 3: 171 ms per loop
%timeit np.array(b)[:, tuple(a)]
# 10 loops, best of 3: 63.1 ms per loop
1 голос
/ 18 июня 2020

Если a должен индексироваться в каждом подсписке, вы можете использовать следующее понимание вложенного списка

>>> [[sub[i] for i in a] for sub in b]
[['B', 'D', 'G'],
 ['I', 'K', 'N'],
 ['P', 'R', 'U']]

Если a и b были numpy.array, также можно было бы

>>> b[:, a]
array([['B', 'D', 'G'],
       ['I', 'K', 'N'],
       ['P', 'R', 'U']], dtype='<U1')
0 голосов
/ 18 июня 2020

Мне нравится использовать map для операций со списками:

list(map(lambda x: [x[i] for i in a], b))
[['B', 'D', 'G'], ['I', 'K', 'N'], ['P', 'R', 'U']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...