2017-08-20 19 views
1

をすべての第二の特定の単語を置き換えるために、私はpythonでこのリストを持っている:どのようにリストに

['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 

そして、私はPearで毎秒Bananaを交換したい(これは結果でなければなりません):

['Pear', 'Apple', 'John', 'Banana', 'Food', 'Pear'] 

私はすでにこのコードを持っている:

with open('text,txt') as f: 
    words = f.read().split() 

words_B = [word if word != 'Banana' else 'Pear' for word in words] 

答えて

1

あなたは、リストCOMPRを使用することができますBananaのすべてのインデックスを取得するehensionし、これらの指標の毎秒を取得してからちょうどPearに対応するリスト項目を設定するスライス:

>>> l = ['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 
>>> for idx in [idx for idx, name in enumerate(l) if name == 'Banana'][::2]: 
...  l[idx] = 'Pear' 
>>> l 
['Pear', 'Apple', 'John', 'Banana', 'Food', 'Pear'] 

代わりに理解をして、また、ジェネレータ式とitertools.isliceを使用することができますスライス:

>>> from itertools import islice 
>>> l = ['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 
>>> for idx in islice((idx for idx, name in enumerate(l) if name == 'Banana'), None, None, 2): 
...  l[idx] = 'Pear' 
>>> l 
['Pear', 'Apple', 'John', 'Banana', 'Food', 'Pear'] 

もう一つの可能​​性、特にあなたがその場であなたのリストを変更したくない場合は、独自のジェネレータ関数を作成することになります。

def replace_every_second(inp, needle, repl): 
    cnt = 0 
    for item in inp: 
     if item == needle: # is it a match? 
      if cnt % 2 == 0: # is it a second occurence? 
       yield repl 
      else: 
       yield item 
      cnt += 1   # always increase the counter 
     else: 
      yield item 

>>> l = ['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 
>>> list(replace_every_second(l, 'Banana', 'Pear')) 
['Pear', 'Apple', 'John', 'Banana', 'Food', 'Pear'] 
+0

「特別な」自動置き換えるコマンドなしでそれを行うための方法はありますか? –

+0

@JohnWinstonうん、私はジェネレータ関数を使って1つのソリューションを追加しました。それがあなたが意味するものなのかどうかは分かりませんが、それは動作していて元のものに取って代わりません。 :) – MSeifert

+0

答えのためのthx、btw 'yield'と 'cnt'は何をするのですか? –

0

(ただ、指摘して、あなたの期待される結果は、あなたがPearで毎秒Bananaを交換する表示されません、それはあなたではなく第二のものより、Banana第一及び第三の交換を示しています。それは本当にあなたが望むものであるならば、あなたは私の次のコードでshouldReplace = TrueshouldReplace = Falseを変更することができます。)

MSeifertのソリューションは、滑らかなで、始まるPythonのユーザーとして私にとって非常に有益だったが、ちょうどそれを行うための別の方法を指すように場所であなたのリストを変更すると、このようなものになるだろう:

def replaceEverySecondInstance(searchWord, replaceWord): 
    shouldReplace = False 
    for index, word in enumerate(words): 
     if word == searchWord: 
      if shouldReplace == True: 
       words[index] = replaceWord 
      shouldReplace = not shouldReplace 

print(words) 
replaceEverySecondInstance('Banana', 'Pear') 
print(words) 

を実行すると、次の出力を提供しますここ

['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 
['Banana', 'Apple', 'John', 'Pear', 'Food', 'Banana'] 
0

は、最後の交換以来、言葉の回出てくるダウンカウントすることによって動作し、一般的なアプローチです:

from collections import defaultdict 

d = defaultdict(int) 
r = { 
    'Banana': 'Pear', 
} 

fruits = ['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 

def replace(fruits, every, first=True): 
    for f in fruits: 
    # see if current fruit f should be replaced 
    if f in r: 
     # count down occurence since last change 
     # -- start at 1 if first should be changed otherwise 0 
     d.setdefault(f, int(not first)) 
     d[f] -= 1 
     # if we have reached count down, replace 
     if d[f] < 0: 
      yield r[f] 
      d[f] = every - 1 
      continue 
    # otherwise append fruit as is 
    yield f 

=>list(replace(fruits, 2, first=True))

['Pear', 'Apple', 'John', 'Banana', 'Food', 'Pear']

=>list(replace(fruits, 2, first=False))

['Banana', 'Apple', 'John', 'Pear', 'Food', 'Banana']

0

ちょっと畳んだけど、私はそれをそこに投げると思った。あなたは、バナナや要素がバナナか、単に元の値である梨とを交互にitertools.cycleを使用してヘルパー関数を使用することができます。例:

from itertools import cycle 

data = ['Banana', 'Apple', 'John', 'Banana', 'Food', 'Banana'] 
b2p = lambda L,c=cycle(['Banana', 'Pear']): next(c) if L == 'Banana' else L 
replaced = [b2p(el) for el in data] 
# ['Banana', 'Apple', 'John', 'Pear', 'Food', 'Banana'] 
関連する問題