Python: Выберите подмножество из списка на основе индексного набора

У меня есть несколько списков, имеющих все равно количество записей (каждое определение свойства объекта):

property_a = [545., 656., 5.4, 33.]
property_b = [ 1.2,  1.3, 2.3, 0.3]
...

и список с флагами той же длины

good_objects = [True, False, False, True]

(которым можно было легко заменить с эквивалентным индексным списком:

good_indices = [0, 3]

Что является самым легким способом генерировать новые списки property_asel, property_bsel... которые содержат только значения, обозначенные любой True записи или индексы?

property_asel = [545., 33.]
property_bsel = [ 1.2, 0.3]
81
задан SilentGhost 5 July 2010 в 13:30
поделиться

3 ответа

Вы можете просто использовать понимание списка :

property_asel = [val for is_good, val in zip(good_objects, property_a) if is_good]

или

property_asel = [property_a[i] for i in good_indices]

Последний быстрее, потому что good_indices меньше, чем длина property_a , предполагая, что good_indices вычисляются предварительно, а не генерируются на лету.


Изменить : первый вариант эквивалентен itertools.compress , доступному с Python 2.7 / 3.1. См. Ответ @Gary Kerr .

property_asel = list(itertools.compress(good_objects, property_a))
103
ответ дан 24 November 2019 в 09:38
поделиться

Я вижу 2 варианта.

  1. Используя numpy:

    property_a = numpy.array([545., 656., 5.4, 33.])
    property_b = numpy.array([ 1.2, 1.3, 2.3, 0.3])
    хорошие_объекты = [True, False, False, True]
    хорошие_индексы = [0, 3]
    property_asel = property_a[good_objects]
    property_bsel = property_b[good_indices]
    
  2. Используем понимание списка и застегиваем его:

    property_a = [545., 656., 5.4, 33.]
    property_b = [ 1.2, 1.3, 2.3, 0.3]
    good_objects = [True, False, False, True]
    good_indices = [0, 3]
    property_asel = [x for x, y in zip(property_a, good_objects) if y]
    property_bsel = [property_b[i] for i in good_indices]
    
22
ответ дан 24 November 2019 в 09:38
поделиться

Используйте встроенную функцию zip

property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]

EDIT

Только что просмотрел новые возможности 2.7. В модуле itertools теперь есть функция, похожая на приведенный выше код.

http://docs.python.org/library/itertools.html#itertools.compress

itertools.compress('ABCDEF', [1,0,1,0,1,1]) =>
  A, C, E, F
15
ответ дан 24 November 2019 в 09:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: