如何从列表中删除不区分大小写的重复项,同时保持原始列表顺序?

Cri*_*ets 7 python list

我有一个字符串列表,如:

myList = ["paper", "Plastic", "aluminum", "PAPer", "tin", "glass", "tin", "PAPER", "Polypropylene Plastic"]
Run Code Online (Sandbox Code Playgroud)

我想要这个结果(这是唯一可接受的结果):

myList = ["paper", "Plastic", "aluminum", "tin", "glass", "Polypropylene Plastic"]
Run Code Online (Sandbox Code Playgroud)

请注意,如果item("Polypropylene Plastic")恰好包含另一个item("Plastic"),我仍然希望保留这两个项目.因此,案例可能会有所不同,但该项必须是字母匹配,以便将其删除.

必须保留原始列表顺序.应删除该项目的第一个实例后的所有重复项.应保留该第一个实例的原始案例,以及所有非重复项的原始案例.

我搜索过,只发现了解决一个需求或另一个需求的问题,而不是两者.

Jea*_*bre 15

由于过滤掉重复项所需的累积/记忆效应,很难用列表理解(或以清晰度为代价)对其进行编码.

它也不可能使用set理解,因为它破坏了原始的顺序.

带循环和辅助的经典方式set,您可以存储您遇到的字符串的小写版本.仅当小写版本不在集合中时,才将字符串存储在结果列表中

myList = ["paper", "Plastic", "aluminum", "PAPer", "tin", "glass", "tin", "PAPER", "Polypropylene Plastic"]
result=[]

marker = set()

for l in myList:
    ll = l.lower()
    if ll not in marker:   # test presence
        marker.add(ll)
        result.append(l)   # preserve order

print(result)
Run Code Online (Sandbox Code Playgroud)

结果:

['paper', 'Plastic', 'aluminum', 'tin', 'glass', 'Polypropylene Plastic']
Run Code Online (Sandbox Code Playgroud)

使用.casefold()而不是.lower()允许在某些区域处理微妙的"套管"差异(如Strasse /Straße中的德国双"s").

编辑:可能通过列表理解来做到这一点,但它确实是hacky:

marker = set()
result = [not marker.add(x.casefold()) and x for x in myList if x.casefold() not in marker]
Run Code Online (Sandbox Code Playgroud)

andNone输出上使用set.add来调用这个函数(列表理解中的副作用,很少是一件好事......),x无论如何都要返回.主要的不利因素是:

  • 可读性
  • casefold()被调用两次,一次用于测试,一次用于存储在标记集中的事实

  • @Alfe人们通常会避免这些副作用. (2认同)