2012-04-23 3 views
8

Пример:Python: Элегантные и эффективные способы маскировки список

from __future__ import division 
import numpy as np 

n = 8 
"""masking lists""" 
lst = range(n) 
print lst 

# the mask (filter) 
msk = [(el>3) and (el<=6) for el in lst] 
print msk 

# use of the mask 
print [lst[i] for i in xrange(len(lst)) if msk[i]] 

"""masking arrays""" 
ary = np.arange(n) 
print ary 

# the mask (filter) 
msk = (ary>3)&(ary<=6) 
print msk 

# use of the mask 
print ary[msk]       # very elegant 

и результаты:

>>> 
[0, 1, 2, 3, 4, 5, 6, 7] 
[False, False, False, False, True, True, True, False] 
[4, 5, 6] 
[0 1 2 3 4 5 6 7] 
[False False False False True True True False] 
[4 5 6] 

Как вы видите, операция маскирования на массиве более изящен по сравнению с список. Если вы попытаетесь использовать массив маскировочную схему в списке, вы получите сообщение об ошибке:

>>> lst[msk] 
Traceback (most recent call last): 
    File "<interactive input>", line 1, in <module> 
TypeError: only integer arrays with one element can be converted to an index 

Вопрос заключается в том, чтобы найти элегантную маскировку для list с.

Обновление:
Ответ на jamylak было принято для введения compress однако точки, упомянутых Joel Cornett сделали решение полностью до желаемой формы моего интереса.

>>> mlist = MaskableList 
>>> mlist(lst)[msk] 
>>> [4, 5, 6] 

ответ

19

Вы ищете itertools.compress

Пример из документации

Эквивалентно:

def compress(data, selectors): 
    # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F 
    return (d for d, s in izip(data, selectors) if s) 
5

С jamylak уже ответил на вопрос с практическим ответом, вот мой пример списка со встроенной поддержкой маскировки (совершенно ненужный, кстати):

from itertools import compress 
class MaskableList(list): 
    def __getitem__(self, index): 
     try: return super(MaskableList, self).__getitem__(index) 
     except TypeError: return MaskableList(compress(self, index)) 

Использование:

>>> myList = MaskableList(range(10)) 
>>> myList 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
>>> mask = [0, 1, 1, 0] 
>>> myList[mask] 
[1, 2] 

Обратите внимание, что compress прекращается, когда либо данные или маска иссякнут. Если вы хотите сохранить часть списка, который проходит мимо длины маски, вы можете попробовать что-то вроде:

from itertools import izip_longest 

[i[0] for i in izip_longest(myList, mask[:len(myList)], fillvalue=True) if i[1]] 
+0

+1 Благодарим вас за то, что вы применяете маскирование списков в виде массивов, предлагая MaskableList.Это выглядит очень интересно и работает очень хорошо, как мое желание. Быстрая заметка заключается в том, что они немного медленнее по сравнению с маскированием массива. Я добавил ваши баллы в качестве обновлений. – Developer

+0

Я попробовал ваше решение 'MaskableList', но у меня есть некоторые проблемы, которые повторно его создают. Для каждого элемента в цикле Я хочу, чтобы замаскировать это, новый список: 'для г в arange (0, п): FTS = MaskableList (F) сортировщика = argsort (А) результата [I] = zip (fts [сортировщик], A [сортировщик]) ' , но каждая итерация, fts [сортировщик] содержит те же значения, тогда как сортировщик различен каждый раз. Я обычно использую python скорее как язык скрипта, и поэтому я не знаком с объектами. –

+0

@ Разработчик: я не тестировал его конкретно, но одна из причин, по которой «MaskableList» может быть значительно медленнее, связана с незначительной дорогостоящей обработкой исключений. Попробуйте переключить 'try ... except', чтобы он по умолчанию маскировался. –

3

я не считаю его элегантным. Он компактен, но имеет тенденцию смущать, поскольку конструкция очень отличается от большинства языков.

Как сказал Россум о дизайне языка, мы тратим больше времени на его чтение, чем написание. Чем более скрытная конструкция строки кода, тем более запутанной она становится для других, которым может не хватать знакомство с Python, хотя они обладают полной компетенцией на любом количестве других языков.

Кодировки удобочитаемости в коротких формах, каждый день в реальном мире кода обслуживания. Так же, как фиксация вашего автомобиля. Большие рисунки с большим количеством информации упрощают поиск неисправностей.

Для меня, я предпочел бы устранить чей-то код, который использует длинную форму

print [lst[i] for i in xrange(len(lst)) if msk[i]] 

чем Numpy короткой маски нотации. Мне не нужно иметь каких-либо специальных знаний о конкретном пакете Python для его интерпретации.

Смежные вопросы