2

その下に、繰り返される文字列で構成される配列があります。これらの文字列を見つけて置換したいのですが、一致するたびに置換文字列の値を変更したいと考えています。

実演させてください。

このサンプル配列:

SampleArray = ['champ', 'king', 'king', 'mak', 'mak', 'mak']

次のように変更する必要があります。

SampleArray = ['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3']

これを可能にする方法は?私は運が悪いので、3日間それを続けてきました。前もって感謝します。

My Failed Code:

import os, collections, re

SampleArray = ['champ', 'king', 'king', 'mak', 'mak', 'mak']
dupes = [x for x, y in collections.Counter(SampleArray).items() if y > 1]
length = len(dupes)
count = 0

while count < length:
    j = 0
    instances = SampleArray.count(dupes[count])
    while j < instances:
        re.sub(dupes[count],  dupes[count] + j, SampleArray, j)
        j += 1
    count += 1
print SampleArray    
print ''; os.system('pause')
4

6 に答える 6

6

collections.Counter を使用します。

from collections import Counter

numbers = { 
    word: iter([""] if count == 1 else xrange(1, count + 1)) 
    for word, count in Counter(sample).items()
}

result = [
    word + str(next(numbers[word])) 
    for word in sample
]

これには、リストをソートまたはグループ化する必要はありません。

このソリューションでは、反復子を使用して連続番号を生成します。

  • まず、各単語がリスト内で何回出現するかを計算します ( Counter(sample))。

  • numbers次に、単語ごとに「番号付け」イテレータを含む辞書を作成しますiter(...)。単語が 1 回だけ出現する場合count==1、この反復子は空の文字列を返します ("yield") [""] if count == 1 else xrange(1, count + 1)

  • 最後に、リストをもう一度反復し、単語ごとに、独自の番号付け iterator から次の値を選択しますnext(numbers[word])。イテレータは数値を返すため、それらを文字列に変換する必要がありますstr(...)

于 2013-06-05T16:00:18.747 に答える
2

groupby重複をグループ化する便利な方法です。

>>> from itertools import groupby
>>> FinalArray = []
>>> for k, g in groupby(SampleArray):
    # g is an iterator, so get a list of it for further handling
    items = list(g)
    # If only one item, add it unchanged
    if len(items) == 1:
        FinalArray.append(k)
    # Else add index at the end
    else:
        FinalArray.extend([j + str(i) for i, j in enumerate(items, 1)])


>>> FinalArray
['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3']
于 2013-06-05T15:54:41.023 に答える
0

配列をソートしたい場合:

import collections    
counter = collections.Counter(SampleArray)
res = []
for key in sorted(counter.keys()):
    if counter[key] == 1:
        res.append(key)
    else:
        res.extend([key+str(i) for i in range(1, counter[key]+1)])

>>> res
['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3']
于 2013-06-05T15:58:58.483 に答える
0

1 つの方法は、次のように配列を辞書に変換することです。

SampleDict = {}
for key in SampleArray:
    if key in SampleDict:
        SampleDict[key][0] = True # means: duplicates
        SampleDict[key][1] += 1 
    else:
        SampleDict[key] = [False, 1] # means: no duplicates

これで、その dict を簡単に配列に戻すことができます。ただし、順序SampleArrayが重要な場合は、次のようにすることができます。

for i in range(len(SampleArray)):
    key = SampleArray[i]
    counter = SampleDict[key]
    if index[0]:
        SampleArray[i] = key + str(counter[1])
    counter[1] -= 1

ただし、これは逆の順序になります。つまり、

SampleArray = ['champ', 'king2', 'king1', 'mak3', 'mak2', 'mak1']

しかし、ニーズに合わせて微調整できると確信しています。

于 2013-06-05T15:39:19.417 に答える
0

編集

並べ替えよりもカウンターと並べ替えの方が簡単です。

L = ['champ', 'king', 'king', 'mak', 'mak', 'mak']
counts = Counter(L)
res = []
for word in sorted(counts.keys()):
    if counts[word] == 1:
        res.append(word)
    else:
        res.extend(['{}{}'.format(word, index) for index in 
                   range(1, counts[word] + 1)])

したがって、この

['champ', 'mak', 'king', 'king', 'mak', 'mak']

も与えます:

['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3']
于 2013-06-05T15:37:35.000 に答える