2016-10-08 3 views
2

私はリストを持っています。リストの元の順序を変更せずに、リスト内の他の文字列の部分文字列である文字列を削除しますか?

the_list = ['Donald Trump has', 'Donald Trump has small fingers', 'What is going on?'] 

、それは他のリスト要素の部分文字列ですので、私はthe_listから「ドナルド・トランプが持っている」削除したいです。

ここは重要な部分です。私は元のリストの順序を逸らすことなくこれをしたい。

私が持っている機能(下記)は元のリストの順序を歪ませます。これは、最初に長さでリスト項目をソートするためです。

def substr_sieve(list_of_strings): 
    dups_removed = list_of_strings[:] 
    for i in xrange(len(list_of_strings)): 
     list_of_strings.sort(key = lambda s: len(s)) 
     j=0 
     j=i+1 
     while j <= len(list_of_strings)-1: 
      if list_of_strings[i] in list_of_strings[j]: 
       try: 
        dups_removed.remove(list_of_strings[i]) 
       except: 
        pass 
      j+=1 
    return dups_removed 
+0

ソートするリストの2番目のコピーを作成してみませんか? – jonrsharpe

+0

@jonrsharpe私はすでにdups_removedのコピーを作っています。私はあなたに従っていないと思う。どのように役立つだろうか? – Aaron

+0

あなたはDivide And Conquer Paradigm – Nishant

答えて

1

あなたはソートせずにこれを行うことができます:

the_list = ['Donald Trump has', "I've heard Donald Trump has small fingers", 
      'What is going on?'] 

def winnow(a_list): 
    keep = set() 
    for item in a_list: 
     if not any(item in other for other in a_list if item != other): 
      keep.add(item) 
    return [ item for item in a_list if item in keep ] 

winnow(the_list) 

ソートは、全体的な少数の比較を可能にすることができるが、それは非常にデータ依存ようで、時期尚早の最適化である可能性があります。

+0

エレガントな回答と動作します(他の回答の一部は機能しません) – Aaron

+0

このデータセットでは失敗しません 'the_list = [' Donald Trump ' 、 "ドナルド"、 "トランプ"、 "ドナルド"、 "ドナルドトランプ"] 'またはその期待出力ですか? – Nishant

+1

OPは、そのケースの予想される出力を指定しませんでした。私の答えは、最も長い文字列のすべての重複を保持します。これは、アイテムが結果に追加されたら 'keep'からアイテムを削除することで修正できます。 'return [(keep.remove(item)、item)[1] a_listのアイテムの場合、keepのアイテムの場合 ' – cco

0

再帰的に項目を減らすことができます。

アルゴリズム:それは維持する必要があるかどうかをポップさせることにより、各項目の上

ループは、決定します。 縮小リストを使用して同じ関数を再帰的に呼び出します。 基本条件は、リストに少なくとも1つの項目(または2つ)があるかどうかです。

効率性:効率的ではない可能性があります。私はいくつかの分割と征服の方法がより適切だろうと思いますか?

the_list = ['Donald Trump has', 'Donald Trump has small fingers',\ 
      'What is going on?'] 

final_list = [] 

def remove_or_append(input): 
    if len(input): 
     first_value = input.pop(0) 
     found = False 
     for each in input: 
      if first_value in each: 
       found = True 
       break 
      else: 
       continue 
     for each in final_list: 
      if first_value in each: 
       found = True 
       break 
      else: 
       continue 
     if not found: 
      final_list.append(first_value) 
     remove_or_append(input) 

remove_or_append(the_list) 

print(final_list) 

A、わずかに異なるバージョンです:

def substring_of_anything_else(item, list): 
    for idx, each in enumerate(list): 
     if idx == item[0]: 
      continue 
     else: 
      if item[1] in each: 
       return True 
     return False 

final_list = [item for idx, item in enumerate(the_list)\ 
       if not substring_of_anything_else((idx, item), the_list)] 
+0

['Donald'、 'Donald']のようなデータセットに問題があります – Nishant

2

単純な解決策です。

しかし、最初のも、それより良いテストケースにするために、最後に「ドナルド・トランプ」、「ドナルド」「トランプ」を追加してみましょう。

>>> forbidden_text = "\nX08y6\n" # choose a text that will hardly appear in any sensible string 
>>> the_list = ['Donald Trump has', 'Donald Trump has small fingers', 'What is going on?', 
     'Donald Trump', 'Donald', 'Trump'] 
>>> new_list = [item for item in the_list if forbidden_text.join(the_list).count(item) == 1] 
>>> new_list 
['Donald Trump has small fingers', 'What is going on?'] 

ロジック:

  1. 単一の文字列を形成するために、すべてのリスト要素を連結します。 forbidden_text.join(the_list)
  2. リスト内の項目が1回だけ発生したかどうかを検索します。 2回以上出現する場合は、サブストリングです。 count(item) == 1

str.count(sub[, start[, end]])

戻り範囲[start, end]におけるサブsubの非重複出現数。オプションの引数startendはスライス表記と解釈されます。


forbidden_textこれらのようなケースを扱うために、(空の文字列)の代わり""のに使用される:

>>> the_list = ['DonaldTrump', 'Donald', 'Trump']


として正しくNishantによって指し示さ、上記のコードはthe_list = ['Donald', 'Donald']で失敗

set(the_list) i the_listのnsteadは問題を解決します。
>>> new_list = [item for item in the_list if forbidden_text.join(set(the_list)).count(item) == 1]

+0

このケースでは動作しますか?the_list = ['Donald Trump'、 'Donald'、 'Trump'] ' – Nishant

+0

このアイデアはとてもいいですが、いくつかのコーナーケースが処理されます。 ['Donald'、 'Donald']は別のものです。しかし、ええ、これは良い代替思考です。 – Nishant

+1

それをセットにしてそれをやっていると私は思っています。 – Nishant

関連する問題