Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找并替换数组中的重复项,但用不同的字符串替换每个第n个实例_Python - Fatal编程技术网

Python 查找并替换数组中的重复项,但用不同的字符串替换每个第n个实例

Python 查找并替换数组中的重复项,但用不同的字符串替换每个第n个实例,python,Python,下面有一个数组,它由重复的字符串组成。我想查找并替换这些字符串,但每次进行匹配时,我都想更改替换字符串的值 让我示范一下 此示例阵列: SampleArray = ['champ', 'king', 'king', 'mak', 'mak', 'mak'] 应更改为: SampleArray = ['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3'] 如何做到这一点?我已经干了三天了,运气不好。提前谢谢 My Failed Code: imp

下面有一个数组,它由重复的字符串组成。我想查找并替换这些字符串,但每次进行匹配时,我都想更改替换字符串的值

让我示范一下

此示例阵列:

SampleArray = ['champ', 'king', 'king', 'mak', 'mak', 'mak']
应更改为:

SampleArray = ['champ', 'king1', 'king2', 'mak1', 'mak2', 'mak3']
如何做到这一点?我已经干了三天了,运气不好。提前谢谢

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')
我的失败代码:
导入操作系统、集合、重新导入
SampleArray=['champ'、'king'、'king'、'mak'、'mak']
dupes=[x代表x,y在collections.Counter(SampleArray).items()中,如果y>1]
长度=长度(重复)
计数=0
当计数<长度时:
j=0
实例=SampleArray.count(重复[count])
而j<实例:
re.sub(重复[count],重复[count]+j,采样阵列,j)
j+=1
计数+=1
打印样本阵列
打印“”;操作系统(‘暂停’)
编辑

计数器和排序比排序更简单:

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']

一种方法是将数组转换为字典,如下所示:

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
for i in range(len(SampleArray)):
    key = SampleArray[i]
    counter = SampleDict[key]
    if index[0]:
        SampleArray[i] = key + str(counter[1])
    counter[1] -= 1
现在您可以轻松地将该dict转换回数组。但是,如果
SampleArray
中的顺序很重要,则可以这样做:

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
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']

但我相信您可以根据自己的需要对其进行调整。

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']

假设要对数组进行排序:

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']

我会使用集合。计数器:

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(…)
    。如果单词只出现一次
    count==1
    ,此迭代器将返回(“yield”)一个空字符串,否则,如果count==1,则它将产生从1到count的序列号
    [“”]

  • 最后,我们再次迭代列表,对于每个单词,从它自己的编号迭代器
    next(number[word])
    中选择下一个值。由于迭代器返回数字,我们必须将它们转换为字符串
    str(…)



难道不应该将champ更改为champ1吗?不,因为它没有被重复,只有king和mak被重复。结果列表中项目的顺序很重要吗?呵呵,当然没有,我在上面发布了我失败的代码。是的,顺序非常重要。你作弊了。champ不会被替换,因为你先附加它,不是因为它只有一个迭代。但为什么它是champ 1而不是champ only?这真的很好,但顺序很重要,不能颠倒,这只会让mak(s)在前面,而king(s)在最后,所以我会等待更好的答案,如果没有,那么我同意您可以使用defaultdict来避免对SampleDict中的键进行测试,计数器通常是用于计算项目的字典。
itertools.groupby
仅对连续项目进行分组,不是吗?很好的注释:这只在重复项是连续的情况下有效。我选择这个答案是因为它不会改变列表顺序,也不会在列表中添加正确的替换字符串。谢谢thg435也谢谢thg435你能解释一下你的代码吗?它有点超过我的理解head@Ahmed:我重新格式化了代码并添加了一些解释。谢谢thg435,解释太棒了。终于明白发生了什么。+1伟大的解决方案<代码>计数器
和iter的组合正确。