Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/350.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中区分相等列表项的最佳方法_Python_List_Equality - Fatal编程技术网

在Python中区分相等列表项的最佳方法

在Python中区分相等列表项的最佳方法,python,list,equality,Python,List,Equality,对于此列表: ['a','a','a,'b','b','c'] 我希望: ['a1','a2','a3','b1','b2','c'] 目的是获取包含不同项目的列表。(len(设置(我的列表))==len(我的列表)) 可以假定列表已排序 并非每个项目都必须出现一次以上(如此处的“c”,在本例中,将其保留) 有很多方法可以做到这一点,我没有想到一个“pythonic”方法。试试这个: lst = ['a','a','a','b','b','c'] [ e + str(i) for i, e

对于此列表:

['a','a','a,'b','b','c']
我希望:

['a1','a2','a3','b1','b2','c']
目的是获取包含不同项目的列表。(
len(设置(我的列表))==len(我的列表)

可以假定列表已排序

并非每个项目都必须出现一次以上(如此处的“c”,在本例中,将其保留)

有很多方法可以做到这一点,我没有想到一个“pythonic”方法。

试试这个:

lst = ['a','a','a','b','b','c']
[ e + str(i) for i, e in enumerate(lst) ]
=> ['a0', 'a1', 'a2', 'b3', 'b4', 'c5']
以上将为所有值生成唯一的名称,只要您不介意为每个字符串使用不同的数字(例如,如果以前使用了
1
,则不会出现
b1

编辑

现在问题已经清楚了,下面是另一个可能的解决方案,使用函数式编程风格:

from collections import Counter

lst = ['a','a','a','b','b','c']
c = Counter(lst)
reduce(lambda a, (k, v): a + ([k + str(i) for i in xrange(1, v+1)] if v > 1 else [k]), c.items(), [])

=> ['a1', 'a2', 'a3', 'c', 'b1', 'b2']

上述操作将更改输入列表中的原始顺序,但如果出现问题,则简单的
sort()
将解决此问题。

使用
collections.Counter
itertools.count

>>> from itertools import count
>>> from collections import Counter
>>> lis = ['a','a','a','b','b','c']
>>> c = Counter(lis)
>>> dic = {k: count(1) for k in c}
>>> [x + ( str(next(dic[x])) if c[x]>1 else '') for x in lis]
['a1', 'a2', 'a3', 'b1', 'b2', 'c']
使用
itertools.groupby
和生成器功能:

>>> def solve(lis):
        for k,g in groupby(lis):
            le = list(g)
            if len(le) > 1:
                for i, x in enumerate(le, 1):
                    yield x+str(i)
            else:        
                yield k
...             
>>> list(solve(lis))
['a1', 'a2', 'a3', 'b1', 'b2', 'c']

您可以使用itertools和其他一些内置函数:

import itertools

data = ['a','a','a','b','b','c']
data_lists = [[y + str(x) for x, y in enumerate(it, 1)] for _, it in itertools.groupby(data)]
result = list(itertools.chain.from_iterable((item if len(item) > 1 else item[0][:-1]) for item in data_lists))

这是一条单行线。。。不高效或不推荐

根据输入:

A = ['a','a','a','b','b','c']
编写输出:

result = [(x + str(A[:i].count(x)) if A.count(x) > 1 else x) for i, x in enumerate(A)]

由于每个人都在发布自己的版本,下面是我使用的
itertools.Counter

>>> counts = Counter(original_list)
>>> [k + (str(i+1) if ct > 1 else "") for k, ct in counts.iteritems() for i in xrange(ct)]
['a1', 'a2', 'a3', 'c', 'b1', 'b2']

请注意,原始列表顺序没有保留。

可能不清楚,但每组(a、b和c)应具有不同的顺序:a1 a2 a3 b1b2@YardenST我用另一种解决方案编辑了我的答案,这次是正确的。我要指出,
reduce
可以替换为
[k+(str(I+1)if ct>1 else”“)对于k,c.iteritems()中的ct,对于xrange(ct)中的i)
,但我非常喜欢我的建议,所以我把它作为我自己的答案发布了出来您需要维持原始订单吗?让
['c','a1','a2','a3','b1','b2']
可以吗?类似/重复:当
枚举
将完成任务时,无需使用
邮政编码(
对于i,枚举(le,1)中的项):
)。也许您忘记了enumerate接受可选的
start
值?@StevenRumbalski很好,解决方案已更新。
>>> counts = Counter(original_list)
>>> [k + (str(i+1) if ct > 1 else "") for k, ct in counts.iteritems() for i in xrange(ct)]
['a1', 'a2', 'a3', 'c', 'b1', 'b2']