2013-08-26 11 views
9

ten jest podobny do niektórych innych pytań (Explicitly select items from a Python list or tuple, Grabbing specific indices of a list in Python), ale szukam zrobić odwrotnie:Python indeksowania z listy wskaźników do Wykluczanie

Co to jest czysty sposób określić listę/krotka indeksy do wykluczyć, zamiast wybrać? Myślę o czymś podobnym do R lub MATLAB, gdzie można określić indeksy wykluczyć, jak:

vector1 <- c('a', 'b', 'c', 'd') 
vector2 <- vector1[-1] # ['b', 'c', 'd'] 
vector3 <- vector1[c(-1, -2)] # ['c', 'd'] 

Czy jest to dobry sposób, aby osiągnąć to samo w Pythonie? Przeprasza, jeśli to dupek, nie byłem pewien, czego dokładnie szukać.

Odpowiedz

10
>>> to_exclude = {1, 2} 
>>> vector = ['a', 'b', 'c', 'd'] 
>>> vector2 = [element for i, element in enumerate(vector) if i not in to_exclude] 

Tutejsze sztuczki to:

  • Użyj listowych do przekształcenia jednej listy do drugiej. (Można również użyć funkcji filter, zwłaszcza jeśli predykat, na którym filtrujesz, jest już umieszczony jako funkcja o ładnej nazwie).
  • Użyj enumerate, aby uzyskać każdy element i jego indeks razem.
  • Użyj operatora in przeciwko dowolnemu typowi Set lub Sequence *, aby zdecydować, które filtry mają być filtrowane. (A set jest najskuteczniejszy, jeśli istnieje wiele wartości i prawdopodobnie koncepcyjnie jest właściwą odpowiedzią ... Ale to naprawdę nie ma większego znaczenia dla niewielu, jeśli masz już listę lub krotkę z 4 indeksami, że to "Set lub Sequence" zbyt, więc można po prostu używać.)

* technicznie rzecz biorąc, każdy Container zrobi. Ale większość Container s, które nie są Set lub Sequence byłoby niemądre tutaj.

+0

Aha, oczywiście. Dziękuję za szczegółowe wyjaśnienie (zaakceptuję to, gdy SO mi pozwoli). –

3

Zastosowanie enumerate() i uwzględniają żadnych wskaźników, które mają zostać usunięte:

[elem for i, elem in enumerate(inputlist) if i not in excluded_indices] 

Dla wydajności byłoby najszybszym jeśli excluded_indices był set.

+0

'set' nie będzie faktycznie szybciej niż' list' dopóki istnieje więcej niż kilka elementów (z poprzedniego pytania, wartość odcięcia wynosi od 3 do 12 z ciągami, w zależności od implementacji). Ale koncepcyjnie i tak ma to więcej sensu. – abarnert

+0

@ABarnert: Czy to też nie zależy od liczby elementów na liście wejściowej? I dla tego filtra może to zrobić różnicę, jeśli 'excluded_indices' jest również sortowane lub randomizowane; Jestem trochę sceptyczny, że granica jest wszędzie * blisko * 12; to jest stały koszt zestawu wyszukiwania (głównie obliczanie i wyszukiwanie skrótu) naprawdę tak wysoki? –

+0

Z tego, co niewyraźnie pamiętam, z bardzo dużymi obiektami 'unicode' w Pythonie 2.7, znalazłem przypadek z odcięciem między 6 a 7 ... ale ktoś inny znalazł przypadek, który był prawie dwa razy wyższy, prawdopodobnie w innej implementacji Pythona. Oczywiście zauważ "ze sznurkami"; hashing ints jest dużo szybszy, nawet ogromny int, więc spodziewałbym się, że w najgorszym razie jest 2-3 ... I nie jestem pewien, jak sortowanie miałoby znaczenie (chyba że chcesz trzeciej implementacji używając 'bisect' lub drzewo lub coś takiego). – abarnert

7
import numpy 
target_list = numpy.array(['1','b','c','d','e','f','g','h','i','j']) 
to_exclude = [1,4,5] 
print target_list[~numpy.in1d(range(len(target_list)),to_exclude)] 

ponieważ numpy jest zabawa

+1

Co więcej, jeśli tłumaczymy kod MATLAB na Python, prawdopodobnie powinniśmy raczej przeglądać numpy zamiast rodzimych list i pętli ... – abarnert

0

wezmę innego podejścia, wykorzystując itemgetter. Tylko dla zabawy :)

from operator import itemgetter 

def exclude(to_exclude, vector): 
    "Exclude items with particular indices from a vector." 
    to_keep = set(range(len(vector))) - set(to_exclude) 
    return itemgetter(*to_keep)(vector) 
1

Korzystając np.delete

In [38]: a 
Out[38]: array([ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) 

In [39]: b 
Out[39]: [3, 4, 5, 9] 

In [40]: a[b] 
Out[40]: array([ 7, 8, 9, 13]) 

In [41]: np.delete(a, b) 
Out[41]: array([ 4, 5, 6, 10, 11, 12])