Python:使用渐进式数字重命名列表中的重复项而不排序列表

pan*_*ish 23 python rename list duplicates

给出这样的列表:

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]
Run Code Online (Sandbox Code Playgroud)

我想通过附加一个数字来重命名重复项,以获得以下结果:

mylist = ["name1", "state", "name2", "city", "name3", "zip1", "zip2"]
Run Code Online (Sandbox Code Playgroud)

我不想改变原始列表的顺序.针对此相关Stack Overflow问题建议的解决方案对列表进行排序,我不想这样做.

小智 13

我的解决方案:maplambda

print map(lambda x: x[1] + str(mylist[:x[0]].count(x[1]) + 1) if mylist.count(x[1]) > 1 else x[1], enumerate(mylist))
Run Code Online (Sandbox Code Playgroud)

更传统的形式

newlist = []
for i, v in enumerate(mylist):
    totalcount = mylist.count(v)
    count = mylist[:i].count(v)
    newlist.append(v + str(count + 1) if totalcount > 1 else v)
Run Code Online (Sandbox Code Playgroud)

最后一个

[v + str(mylist[:i].count(v) + 1) if mylist.count(v) > 1 else v for i, v in enumerate(mylist)]
Run Code Online (Sandbox Code Playgroud)


Ric*_*ica 13

我就是这样做的.

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]
check = ["name1", "state", "name2", "city", "name3", "zip1", "zip2"]
copy = mylist[:]  # so we will only mutate the copy in case of failure

from collections import Counter # Counter counts the number of occurrences of each item
from itertools import tee, count

def uniquify(seq, suffs = count(1)):
    """Make all the items unique by adding a suffix (1, 2, etc).

    `seq` is mutable sequence of strings.
    `suffs` is an optional alternative suffix iterable.
    """
    not_unique = [k for k,v in Counter(seq).items() if v>1] # so we have: ['name', 'zip']
    # suffix generator dict - e.g., {'name': <my_gen>, 'zip': <my_gen>}
    suff_gens = dict(zip(not_unique, tee(suffs, len(not_unique))))  
    for idx,s in enumerate(seq):
        try:
            suffix = str(next(suff_gens[s]))
        except KeyError:
            # s was unique
            continue
        else:
            seq[idx] += suffix

uniquify(copy)
assert copy==check  # raise an error if we failed
mylist = copy  # success
Run Code Online (Sandbox Code Playgroud)

编辑:这是一个单行,但订单不保留.

>>> mylist = ["name", "state", "name", "city", "name", "zip", "zip"]
>>> uniquify(mylist, (f'_{x!s}' for x in range(1, 100)))
>>> mylist
['name_1', 'state', 'name_2', 'city', 'name_3', 'zip_1', 'zip_2']
Run Code Online (Sandbox Code Playgroud)


DTi*_*ing 7

其中的任何方法count被称为每个元素会导致O(n^2)countIS O(n).你可以这样做:

# not modifying original list
from collections import Counter

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]
counts = {k:v for k,v in Counter(mylist).items() if v > 1}
newlist = mylist[:]

for i in reversed(range(len(mylist))):
    item = mylist[i]
    if item in counts and counts[item]:
        newlist[i] += str(counts[item])
        counts[item]-=1
print(newlist)

# ['name1', 'state', 'name2', 'city', 'name3', 'zip1', 'zip2']
Run Code Online (Sandbox Code Playgroud)
# modifying original list
from collections import Counter

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]
counts = {k:v for k,v in Counter(mylist).items() if v > 1}      

for i in reversed(range(len(mylist))):
    item = mylist[i]
    if item in counts and counts[item]:
        mylist[i] += str(counts[item])
        counts[item]-=1
print(mylist)

# ['name1', 'state', 'name2', 'city', 'name3', 'zip1', 'zip2']
Run Code Online (Sandbox Code Playgroud)

这应该是O(n).

其他提供的答案:

mylist.index(s) 每个元素导致 O(n^2)

mylist = ["name", "state", "name", "city", "name", "zip", "zip"]

from collections import Counter
counts = Counter(mylist)
for s,num in counts.items():
    if num > 1:
        for suffix in range(1, num + 1):
            mylist[mylist.index(s)] = s + str(suffix) 
Run Code Online (Sandbox Code Playgroud)

count(x[1])每个元素的原因每个元素O(n^2)
也使用多次以及列表切片.

print map(lambda x: x[1] + str(mylist[:x[0]].count(x[1]) + 1) if mylist.count(x[1]) > 1 else x[1], enumerate(mylist))
Run Code Online (Sandbox Code Playgroud)

基准:

http://nbviewer.ipython.org/gist/dting/c28fb161de7b6287491b


ron*_*akg 7

这是一个非常简单的O(n)解决方案。只需遍历存储列表中元素索引的列表即可。如果我们之前看过此元素,请更早使用存储的数据附加出现值。

这种方法通过仅创建一个更多的字典来解决问题。避免前瞻,以免我们不创建临时列表片。

mylist = ["name", "state", "name", "city", "city", "name", "zip", "zip", "name"]

dups = {}

for i, val in enumerate(mylist):
    if val not in dups:
        # Store index of first occurrence and occurrence value
        dups[val] = [i, 1]
    else:
        # Special case for first occurrence
        if dups[val][1] == 1:
            mylist[dups[val][0]] += str(dups[val][1])

        # Increment occurrence value, index value doesn't matter anymore
        dups[val][1] += 1

        # Use stored occurrence value
        mylist[i] += str(dups[val][1])

print mylist

# ['name1', 'state', 'name2', 'city1', 'city2', 'name3', 'zip1', 'zip2', 'name4']
Run Code Online (Sandbox Code Playgroud)

  • 是的,我知道`collections.Counter` :)。我只是想发布一个更有效的解决方案。此解决方案仅执行列表的一次传递。 (2认同)