【问题标题】:How to append count numbers to duplicates in a list in Python?如何将计数附加到 Python 列表中的重复项?
【发布时间】:2020-06-10 23:42:52
【问题描述】:

这是一个包含重复项的列表:

l1 = ['a', 'b', 'c', 'a', 'a', 'b']

这是想要的结果:

l1 = ['a', 'b', 'c', 'a_1', 'a_2', 'b_1']

如何通过附加计数来重命名重复项?


这是实现这一目标的尝试;但是,有没有更 Pythonic 的方式?

for index in range(len(l1)):
    counter = 1
    list_of_duplicates_for_item = [dup_index for dup_index, item in enumerate(l1) if item == l1[index] and l1.count(l1[index]) > 1]
    for dup_index in list_of_duplicates_for_item[1:]: 
        l1[dup_index] = l1[dup_index] + '_' + str(counter)
        counter = counter + 1

【问题讨论】:

  • 我想你想要'a_1'而不是'a'_1?

标签: python list duplicates


【解决方案1】:

在 Python 中,生成新列表通常比更改现有列表容易得多。我们有生成器可以有效地做到这一点。 dict 可以记录出现次数。

l = ['a', 'b', 'c', 'a', 'a', 'b']

def rename_duplicates( old ):
    seen = {}
    for x in old:
        if x in seen:
            seen[x] += 1
            yield "%s_%d" % (x, seen[x])
        else:
            seen[x] = 0
            yield x

print list(rename_duplicates(l))

【讨论】:

  • +1 我写了与类相同的解决方案,但这更好,生成器比此类工作更 Pythonic,无论如何我都看到了。
  • 这个解决方案对我有用,但我想附加一个字母而不是一个数字。 seen[x] += 1; character = str(chr(96+seen[x])); yield "%s_%s" % (x, character);
【解决方案2】:

我会这样做:

a1 = ['a', 'b', 'c', 'a', 'a', 'b']
a2 = []

d = {}

for i in a1:

    d.setdefault(i, -1)
    d[i] += 1

    if d[i] >= 1:
        a2.append('%s_%d' % (i, d[i]))
    else:
        a2.append(i)

print a2

【讨论】:

    【解决方案3】:

    根据您对@mathmike 的评论,如果您的最终目标是从具有重复键的列表中创建一个字典,我会使用来自`collections Lib 的defaultdict

    >>> from collections import defaultdict
    >>> multidict = defaultdict(list)
    >>> multidict['a'].append(1)
    >>> multidict['b'].append(2)
    >>> multidict['a'].append(11)
    >>> multidict
    defaultdict(<type 'list'>, {'a': [1, 11], 'b': [2]})
    

    【讨论】:

      【解决方案4】:

      我认为您要求的输出本身很混乱,因此没有干净的方法来创建它。

      您打算如何使用这个新列表?像下面这样的计数字典会起作用吗?

      {'a':3, 'b':2, 'c':1}
      

      如果是这样,我会推荐:

      from collections import defaultdict
      d = defaultdict(int) # values default to 0
      for key in l1:
          d[key] += 1
      

      【讨论】:

      • 嘿!感谢所有的答复。 =) 我想保留重复的原因是因为该列表实际上将是一个字典将使用的键列表,我不想无意中覆盖相同的键。 =)
      【解决方案5】:

      我编写了这种方法,用于使用任何分隔符和数字或字母后缀(例如 _1、_2 或 _a、_b、_c 等)重命名列表中的重复项。可能不是你能写出的最好的高效代码,但我喜欢它是一个干净易读的代码,它也很容易扩展。

      def rename_duplicates(label_list, seperator="_", mode="numeric"):
      
          """
          options for 'mode': numeric, alphabet
      
          """
          import string
      
          if not isinstance(label_list, list) or not isinstance(seperator, str):
              raise TypeError("lable_list and separator must of type list and str, respectively")
      
          for item in label_list:
      
              l_count = label_list.count(item)
      
              if l_count > 1:
      
                  if mode == "alphabet":
                      postfix_str = string.ascii_lowercase
      
                      if len(postfix_str) < l_count:
                          # do something
                          pass
      
                  elif mode == "numeric":
                      postfix_str = "".join([str(i+1) for i in range(l_count)])
      
                  else:
                      raise ValueError("the 'mode' could be either 'numeric' or 'alphabet'")
      
                  postfix_iter = iter(postfix_str)
      
                  for i in range(l_count):
                      item_index = label_list.index(item)
                      label_list[item_index] += seperator + next(postfix_iter)
      
          return label_list
      

      label_list = ['a', 'b', 'c', 'a', 'a', 'b']

      使用函数: rename_duplicates(label_list)

      结果: ['a_1', 'b_1', 'c', 'a_2', 'a_3', 'b_2']

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-08
        • 2019-06-23
        • 1970-01-01
        • 2013-12-30
        • 2013-06-18
        • 2019-05-30
        • 2013-07-28
        • 2020-08-06
        相关资源
        最近更新 更多