我有一个列表,我想生成一个字典d
取出重复项并排除单个项目,这样第一个键的值为0,第二个键的值为1,依此类推。
我写了以下代码:
d = {}
i = 0
for l in a_list:
if (l not in d) and (l != '<'):
d[l] = i
i += 1
如果a_list = ['a', 'b', '<', 'c', 'b', 'd']
,则在运行代码d
后包含{'a': 0, 'b': 1, 'c': 2, 'd':3}
。订单并不重要。
是否有更优雅的方法来获得相同的结果?
答案 0 :(得分:5)
使用dict.fromkeys
获取您的独特事件(减去您不想要的值),然后使用.update
来应用序列,例如:
a_list = ['a', 'b', '<', 'c', 'b', 'd']
d = dict.fromkeys(el for el in a_list if el != '<')
d.update((k, i) for i, k in enumerate(d))
给你:
{'a': 0, 'b': 1, 'd': 2, 'c': 3}
如果订单很重要,请使用collections.OrderedDict.fromkeys
保留原始值的排序,或者如果它们应该按字母顺序排列,则对唯一值进行排序。
答案 1 :(得分:3)
{b: a for a, b in enumerate(set(a_list) - {'<'})}
set(a_list)
从a_list
创建一个集合。
这有效地删除了a_list
中的重复数字,因为set
只能包含唯一值。
答案 2 :(得分:2)
这里需要的是ordereddict并手动过滤列表:
from collections import OrderedDict
d = OrderedDict()
new_list = []
a_list = [1,3,2,3,2,1,3,2,3,1]
for i in a_list:
if i not in new_list:
new_list.append(i)
for i, a in enumerate(new_list):
if a != "<":
d[i] = a
输出:
OrderedDict([(0, 1), (1, 3), (2, 2)])
如果原始订单不重要:
final_d = {i:a for i, a in enumerate(set(a_list)) if a != "<"}
答案 3 :(得分:2)
我个人觉得递归相当优雅,尾递归尤其如此:
def f( d, a_list ):
if a_list:
if a_list[0] not in d and a_list[0] != '<':
d[a_list[0]] = len(d)
return f( d, a_list[1:] )
else:
return d
那样
f( {}, "acbcbabcbabcb" )
将产生
{'a': 0, 'c': 1, 'b': 2}
就像原始代码在同一输入上做的那样(键的模数顺序)。
答案 4 :(得分:1)
如果真的:
订单并不重要。
{k: i for i, k in enumerate(filter(lambda x: x not in "<", set(a_list)))}
# {'a': 3, 'b': 1, 'c': 0, 'd': 2}
编辑:@qnnnnez的答案利用了集合操作,给出了后一种代码的优雅版本。
否则,您可以实施unique_everseen
itertools recipe来保留订单。为方便起见,您可以从为您实现此配方的库中导入它,即more_itertools
。
from more_itertools import unique_everseen
{k: i for i, k in enumerate(filter(lambda x: x not in "<", unique_everseen(a_list)))}
# {'a': 0, 'b': 1, 'c': 2, 'd': 3}