Mam kilka list mających tę samą liczbę wpisów (każda z określeniem właściwości obiektu):
property_a = [545., 656., 5.4, 33.]
property_b = [ 1.2, 1.3, 2.3, 0.3]
...
i lista z flagami o tej samej długości
good_objects = [True, False, False, True]
(który można łatwo zastąpić równoważną listą indeksów:
good_indices = [0, 3]
Jaki jest najłatwiejszy sposób generowania nowych list property_asel
, property_bsel
... które zawierają tylko wartości wskazane przez True
wpisy lub indeksy?
property_asel = [545., 33.]
property_bsel = [ 1.2, 0.3]
zip
w Pythonie 2 utworzy nową listę, ale w Pythonie 3 zwróci (leniwy) generator.from itertools import izip
i użyć zamiastzip
w pierwszym przykładzie. To tworzy iterator, taki sam jak Python 3.Widzę 2 opcje.
Korzystanie numpy:
property_a = numpy.array([545., 656., 5.4, 33.]) property_b = numpy.array([ 1.2, 1.3, 2.3, 0.3]) good_objects = [True, False, False, True] good_indices = [0, 3] property_asel = property_a[good_objects] property_bsel = property_b[good_indices]
Korzystanie z listy i spakowanie jej:
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]
źródło
[property_b[i] for i in good_indices]
jest dobry do używania beznumpy
Użyj wbudowanej funkcji zip
property_asel = [a for (a, truth) in zip(property_a, good_objects) if truth]
EDYTOWAĆ
Wystarczy spojrzeć na nowe funkcje wersji 2.7. W module itertools znajduje się teraz funkcja podobna do powyższego kodu.
http://docs.python.org/library/itertools.html#itertools.compress
itertools.compress('ABCDEF', [1,0,1,0,1,1]) => A, C, E, F
źródło
itertools.compress
tutaj. Zrozumienie listy jest dużo bardziej czytelne, bez konieczności odkrywania tego, co robi kompres.itertools.compress
zamiast kopiować, wklejając przykład dokumentacji?Zakładając, że masz tylko listę pozycji i listę prawdziwych / wymaganych wskaźników, powinno to być najszybsze:
property_asel = [ property_a[index] for index in good_indices ]
Oznacza to, że wybór właściwości wykona tylko tyle rund, ile jest prawdziwych / wymaganych wskaźników. Jeśli masz wiele list właściwości, które są zgodne z regułami pojedynczej listy tagów (prawda / fałsz), możesz utworzyć listę indeksów, korzystając z tych samych zasad rozumienia list:
good_indices = [ index for index, item in enumerate(good_objects) if item ]
To iteruje przez każdy element w good_objects (pamiętając jego indeks z enumerate) i zwraca tylko indeksy, w których element jest prawdziwy.
Dla każdego, kto nie rozumie listy, oto angielska proza z kodem wyróżnionym pogrubioną czcionką:
notować indeksu dla każdej grupy indeks, przedmiot , który istnieje w na wyliczenie z dobrymi obiektami , jeśli (gdzie) pozycja jest prawda
źródło
Języki Matlab i Scilab oferują prostszą i bardziej elegancką składnię niż Python dla pytania, które zadajesz, więc myślę, że najlepsze, co możesz zrobić, to naśladować Matlab / Scilab za pomocą pakietu Numpy w Pythonie. W ten sposób rozwiązanie problemu jest bardzo zwięzłe i eleganckie:
from numpy import * property_a = array([545., 656., 5.4, 33.]) property_b = array([ 1.2, 1.3, 2.3, 0.3]) good_objects = [True, False, False, True] good_indices = [0, 3] property_asel = property_a[good_objects] property_bsel = property_b[good_indices]
Numpy próbuje naśladować Matlab / Scilab, ale ma to swoją cenę: musisz zadeklarować każdą listę ze słowem kluczowym "array", co spowoduje przeciążenie twojego skryptu (ten problem nie istnieje w Matlab / Scilab). Zauważ, że to rozwiązanie jest ograniczone do tablic liczb, co ma miejsce w twoim przykładzie.
źródło
filter
biblioteki Pythona lub biblioteki zewnętrznejpandas
. Jeśli zamierzasz zamienić języki, możesz również spróbować R, ale nie o to chodzi w pytaniu .