通过在重复项中附加一个字母,使列表中的项目唯一

时间:2018-04-28 19:20:14

标签: python list

我有一些数字列表,其中一些重复,如下所示。

list = [101,101,102,103,103,103,104,105,106,107,108,108,108,108]

当列表中的数字重复时,我需要按顺序追加一个字母,如101将变为101A和101B以及103A和103B和103C。依此类推。

有没有人知道在Python中这样做的方法。

我希望最终得到这样的列表。

list = [101A,101B,102,103A,103B,103C,104,105,106,107,108A,108B,108C,108D]

4 个答案:

答案 0 :(得分:1)

如上所述,字母用完时没有明确的行为。此示例也不使用ord()或chr():

#!/usr/bin/env python

lst1 = [101, 101, 102, 103, 103, 103, 104, 105, 106, 107, 108, 108, 108, 108]
alphabet = ["", "A", "B", "C", "D", "E"]

NewList = []
dictionary = {}
for i in lst1:
    if i in dictionary:
        dictionary[i] += 1
        letter = alphabet[dictionary[i]]
        NewList.append("{}{}".format(i, letter))
        continue
    else:
        dictionary[i] = 0
        letter = alphabet[dictionary[i]]
        NewList.append("{}{}".format(i, letter))


print(NewList)

哪个输出:

['101A', '101B', '102A', '103A', '103B', '103C', '104A', '105A', '106A', '107A', '108A', '108B', '108C', '108D']

答案 1 :(得分:1)

使用itertools.groupby的解决方案:

import itertools
import string

x = [101,101,102,103,103,103,104,105,106,107,108,108,108,108]
x = list(map(str, x))

def zip_letters(l):
  al = string.ascii_uppercase
  return [''.join(i) for i in zip(l, al)] if len(l) > 1 else l


x = [j for _, i in itertools.groupby(x) for j in zip_letters(list(i)) ]
print(x)

输出:

['101A', '101B', '102', '103A', '103B', '103C', '104', '105', '106', '107', '108A', '108B', '108C', '108D']

答案 2 :(得分:0)

执行此操作的一种方法是itertools.groupby(假设只有连续数字),然后zip在相关字母上(如果适用),例如:

In []:
import string
l = [101,101,102,103,103,103,104,105,106,107,108,108,108,108]
m = [list(g) for _, g in it.groupby(map(str, l))]
[''.join(x) for g in m for x in zip(g, string.ascii_uppercase if len(g) > 1 else [''])]

Out[]:
['101A', '101B', '102', '103A', '103B', '103C', '104', '105', '106', '107', '108A', '108B', '108C', '108D']

目前的方法要求您提前了解是否有多个号码可以开始附加字母。这可以通过在每个号码上附加一个字母或者在任何第一次出现任何号码时都没有字母来避免 注意:以下两种方法都不关心连续编号。

每个号码都写一封信:

In []:
d = {}
['{}{}'.format(x, next(d.setdefault(x, iter(string.ascii_uppercase)))) for x in l]

Out[]:
['101A', '101B', '102A', '103A', '103B', '103C', '104A', '105A', '106A', '107A', '108A', '108B', '108C', '108D']

或者,如果您不介意['101', '101A', '102', ...]

In []:
d = {}
letters = [''] + list(string.ascii_uppercase)
['{}{}'.format(x, next(d.setdefault(x, iter(letters)))) for x in l]

Out[]:
['101', '101A', '102', '103', '103A', '103B', '104', '105', '106', '107', '108', '108A', '108B', '108C']

答案 3 :(得分:0)

这是我提出的解决方案。它可能不是最高效的,而且有点过于复杂,但我觉得它很有趣。

from string import ascii_uppercase
from collections import defaultdict

class Maybe_A:
    def __init__(self):
        self.is_a = False
    def __str__(self):
        return 'A' if self.is_a else ''

def letters():
    a = Maybe_A()
    yield a
    a.is_a = True
    yield from ascii_uppercase[1:]

def tag_duplicates(l):
    d = defaultdict(letters)
    pre_process = [(s, next(d[s])) for s in (str(number) for number in l)]
    return [x+str(y) for x, y in pre_process]

print(tag_duplicates([101,101,102,103,103,103,104,105,106,107,108,108,108,108]))
# ['101A', '101B', '102', '103A', '103B', '103C', '104', '105', '106', '107', '108A', '108B', '108C', '108D']