2017-05-27 3 views
-1

Ich habe ein Array, das mehrere Elemente mit einem gemeinsamen Präfix und ein anderes Array enthält, das eine Liste der auszuschließenden Elemente enthält, aber ohne das Präfix. Ich möchte das Präfix von allen Elementen entfernen und diejenigen ausschließen, die ausgeschlossen werden müssen. Zum Beispiel:Ändern und Ausschließen einiger Elemente in einem Array

fullList = ['foo-1', 'foo-2', 'foo-3', 'foo-4', 'foo-5'] 
exclude = ['2', '4', '6'] 

Ich möchte, als Ergebnis fullList enthalten nur ['1', '3', '5']. Ich könnte es leicht mit einer Schleife machen, aber ich würde es lieber mit einem Verständnis machen. Zur Zeit mache ich es in zwei Schritten:

fullList = [element.replace('foo-', '') for element in fullList] 
fullList = [element for element in fullList if element not in exclude] 

Ich frage mich - gibt es einen besseren Weg, und vor allem kann ich es tut mit in einem einzigen Schritt?

Antwort

3

In einem Schritt können Sie es wie so tun:

[f.replace('foo-', '') for f in fullList if all(ex not in f for ex in exclude)] 
# ['1', '3', '5'] 

oder nach Ihrer ursprünglichen Logik, können Sie das erste Verständnis in die zweite als Generator einbetten:

[f_trim for f_trim in (f.replace('foo-', '') for f in fullList) if f_trim not in exclude] 
# ['1', '3', '5'] 

Verwenden Sie ein Stellen Sie ein, wenn die Listen groß sind:

excludeSet = set(exclude) 
[f_trim for f_trim in (f.replace('foo-', '') for f in fullList) if f_trim not in excludeSet] 

Wenn Sie Leistung betrachten, und für bessere r eadability, können Sie zwei Linien halten mit dem ersten als Generator:

excludeSet = set(exclude) 
trimList = (f.replace('foo-', '') for f in fullList) 
[e for e in trimList if e not in excludeSet] 
+1

Ich mag die Einfachheit der ersten Lösung. – bontchev

+0

@bontchev - das ist auch eine falsche Lösung, bedenke 'fullList = ['foo-1', 'foo-3', 'foo-5', 'foo-7', 'foo-11', 'foo-13' , 'foo-17', 'foo-19'] 'und' exclude = ['1', '7'] '. Sie würden erwarten, dass Ihr Ergebnis '[' 3 ',' 5 ',' 11 ',' 17 ',' 19 '] 'ist, aber das erste Beispiel gibt Ihnen nur' ['3', '5']' da es eine vollständige String-Suche jedes "exclude" -Elements über jedes 'fullList'-Element durchführt, so dass" 1 "mit jedem Element übereinstimmt, das" 1 "enthält. – zwer

+0

In der Tat sollte "ex nicht in f" durch das strengere "nicht mit (ex)" ersetzt werden. – bontchev

4
fullList = ['foo-1', 'foo-2', 'foo-3', 'foo-4', 'foo-5'] 
exclude = ['2', '4', '6'] 

diese Methode Betrachten, das funktioniert nur für eine einstellige Zahl nach foo-:

fullList = list([x[-1] for x in fullList if x[-1] not in exclude]) 

Wenn Sie jetzt versuchen fullList zu drucken, erhalten Sie:

['1', '3', '5'] 

Beachten Sie, dass für eine Zeichenfolge, s[-1] gibt sein letztes Zeichen zurück (z. B. 'abc'[-1] ergibt 'c').


Lösung, die auch für mehr als eine einstellige Zahl arbeitet nach foo-:

fullList = list([x.replace('foo-','') for x in fullList if x.replace('foo-','') not in exclude]) 
+1

Ordentlich! Der Nachteil ist, dass es nur mit einzelnen Ziffern funktioniert. Ich würde "exclude" auch in einen Satz umwandeln, wenn es eine größere Liste wäre. – zwer

+0

@zwer behoben. mach es auch für mehr als eine Ziffer :) –

+0

Leider war das, was ich in meiner Frage gab, nur ein Beispiel; In Wirklichkeit habe ich eine ganze Zeichenfolge nach dem gemeinsamen Präfix, daher ist die erste Lösung nicht akzeptabel. Ich dachte selbst über die zweite Lösung nach, aber zweimal 'replace()' zu nennen, schien unelegant. – bontchev

2

Im Anschluss an Mr. Xcoder auf der Spur, würde ich eine zusätzliche Optimierung für maximale Geschwindigkeit vorschlagen:

# exclude = set(exclude) # uncomment if the exclude list is big 
fullList = [x[4:] for x in fullList if x[4:] not in exclude] 
# ['1', '3', '5'] 

Der 4 Index ist von unserem Vorwissen über die Länge foo- abgeleitet. Das direkte Slicen sollte wesentlich schneller sein als ein Funktionsaufruf und eine Suche & ersetzen Verfahren.

+0

Froh, dass mich jemand versteht :) –

Verwandte Themen