Следующий код Python выглядит очень длинным при использовании фона Matlab.
>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]
В Matlab я могу написать:
>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
3 6
Есть ли короткий способ написать это на Python, или я просто буду придерживаться длинной версии?
Спасибо за все предложения и объяснения причин синтаксиса Python.
Найдя на сайте numpy следующее, я думаю, что нашел решение, которое мне нравится:
http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays
Применение информации с этого веб-сайта к моей проблеме выше дало бы следующее:
>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]
Следующее должно работать (но у меня нет под рукой интерпретатора Python для его тестирования):
class my_array(numpy.array):
def find(self, b):
r = array(range(len(b)))
return r(b)
>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]
[idx for idx in range(len(a)) if a[idx] > 2]
? Причина, по которой это немного неудобно делать в Python, заключается в том, что он не использует индексы так часто, как другие языки.Ответы:
В Python вы вообще не будете использовать для этого индексы, а просто будете иметь дело со значениями -
[value for value in a if value > 2]
. Обычно работа с индексами означает, что вы делаете что-то не лучшим образом.Если вам действительно нужен API , похожий на Matlab, вы бы использовать NumPy , пакет для многомерных массивов и численной математики в Python , который сильно вдохновлен Matlab. Вы бы использовали массив numpy вместо списка.
источник
filtered_ranges_and_angles = [(range, angle) for range, angle in zip(ranges, angles) if should_be_kept(range)]
По-другому:
В общем, помните, что, хотя
find
это уже готовая функция, составление списков - это общее и, следовательно, очень мощное решение . Ничто не мешает написатьfind
функцию на Python и использовать ее в дальнейшем по своему желанию. То есть:Обратите внимание, что здесь я использую списки для имитации Matlab. Было бы более Pythonic использовать генераторы и итераторы.
источник
[i for i,v in enumerate(a) if v > 2]
.index
сi
иvalue
сv
в оригинале и сосчитать символы.enumerate
overrange(len(...))
более надежно и эффективно.find_indices
функцию для использованияenumerate
Для меня это хорошо работает:
источник
Может быть, другой вопрос: «Что вы собираетесь делать с этими индексами, когда они у вас есть?» Если вы собираетесь использовать их для создания другого списка, то в Python они являются ненужным промежуточным шагом. Если вам нужны все значения, которые соответствуют заданному условию, просто используйте встроенный фильтр:
Или напишите свой собственный список:
Если вы хотите удалить их из списка, то способ Pythonic не обязательно удалять из списка, а написать понимание списка, как если бы вы создавали новый список, и назначаете его обратно на месте с
listvar[:]
помощью слева -сторона:Matlab поставляет,
find
потому что его модель, ориентированная на массивы, работает путем выбора элементов с использованием их индексов массива. Вы , конечно, можете сделать это в Python, но более питонический способ заключается в использовании итераторов и генераторов, как уже упоминалось @EliBendersky.источник
a[:] = ...
- см. Ответ Алекса Мартелли на этот вопрос stackoverflow.com/questions/1352885/… .Даже если это запоздалый ответ: я думаю, что это все еще очень хороший вопрос, и IMHO Python (без дополнительных библиотек или инструментов, таких как numpy) по-прежнему не имеет удобного метода для доступа к индексам элементов списка в соответствии с вручную определенным фильтром.
Вы можете вручную определить функцию, которая обеспечивает эту функциональность:
Доходность: [0, 4]
В моем воображении идеальным способом было бы создать дочерний класс списка и добавить функцию index как метод класса. Таким образом, потребуется только метод фильтрации:
Я подробно остановился на этой теме здесь: http://tinyurl.com/jajrr87
источник