2016-12-07 9 views
3

これは簡単な質問だと思います。Python:リスト内包表記を使用してサブストリングのリストでリストをフィルタリングする

これら二つのリストを考える:私はリスト内包したい

result = ['c'] 

こと:どのように私は結果は次のようになりようにリストxをフィルタリングするリスト内包を書くのです

x = ['a', 'ab', 'abc', 'bc', 'c', 'ac'] 
y = ['a', 'b'] 

y内の文字列の部分一致をx内の文字列に除外します。たとえば、yの 'a'はxの 'a'、 'ab'、 'abc'、および 'ac'と一致します。これはすでに、私は喜んで前の回答へのリンクを受け入れるだろう依頼されている場合はresult = [r for r in x if r not in y]

この理解は全体の文字列にマッチします。それはまだ、私はまだそれが見つかりませんでした。

答えて

9

使用all

result = [r for r in x if all(z not in r for z in y)] 

またはany

result = [r for r in x if not any(z in r for z in y)] 
+0

これでした。私は任意のステートメントを持っていましたが、あなたの例ではzとrの変数は逆になりました。ボーナス:私は「すべて」について学んだだけです。ありがとう! – craignewkirk

2

これはanyビルトインのための仕事です。

>>> x = ['a', 'ab', 'abc', 'bc', 'c', 'ac'] 
>>> y = ['a', 'b'] 
>>> [r for r in x if not any(s in r for s in y)] 
['c'] 

s in rあなたがしたい部分一致、for s in yチェックyのすべての要素を行い、そして任意の試合があった場合anyはtrueです。それから、それを逆転させます。

これは2次式であり、O(len(x) * len(y))です。 yが長い場合は、正規表現を合成するために、より効率的であってもよい:単にO(len(x) + len(y))であるべきである

>>> import re 
>>> yy = re.compile("|".join(re.escape(s) for s in y)) 
>>> [r for r in x if not yy.search(r)] 
['c'] 

1

あなたのyの長さによって決まります。多くの要素が含まれていれば、それをセットに変換し、xのアイテムに交差点(1つの共通文字)があるかどうかを確認します。

y = set(y) 
[item for item in x if not y.intersection(item)] 
+0

これは 'y'は長さ1の文字列しか含まないことを前提としています。この例では、指定されていません。 –

+0

はい、これ以上の文字が含まれていると、これは間違いなく機能しません。しかし、一方では、 'y'だけが一文字しか含まれていないと、はるかに高速です。 :-) – MSeifert

+0

私の実際のプロジェクトでは、これは部分文字列によるURLのリストをフィルタリングするために使用されています。 – craignewkirk

関連する問題