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

2024-06-09 21:39:59 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

^{pr2}$

注意,如果一个项目("Polypropylene Plastic")碰巧包含另一个项目("Plastic"),我仍然希望保留这两个项目。因此,大小写可以不同,但项目必须是字母对字母匹配,才能将其删除。在

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

我搜索了一下,只找到了一个或另一个需要的问题,而不是两者都有。在


Tags: 项目实例字符串列表字母案例papertin
3条回答

很难用列表理解来编写代码(或者以牺牲清晰度为代价),因为你需要过滤掉重复项的累积/内存效应。在

也不可能使用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)

结果:

^{pr2}$

使用.casefold()代替.lower()可以处理某些区域设置中细微的“大小写”差异(如Strasse/Straße中的德语双“s”)。在

编辑:用列表理解可以做到这一点,但这确实很难做到:

marker = set()
result = [not marker.add(x.casefold()) and x for x in myList if x.casefold() not in marker]

它在set.addNone输出上使用and来调用这个函数(在列表理解中有副作用,很少是好事…),并且无论如何都要返回x。主要缺点是:

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

编辑:好吧,我修改了我的答案,因为问题同时改变了。 现在,它检查是否在原始列表中找到了大写的单词,并在没有找到时将其转换为小写。在

import string

def custom_filter(my_list):
    seen = set()
    result_list = []
    for i in my_list:
        item = string.capwords(i)
        if item not in my_list:
            item = item.lower()
        if item not in seen:
            result_list.append(item)
            seen.add(item)
    return result_list


print(custom_filter(myList))

输出:

^{pr2}$
import pandas as pd
df=pd.DataFrame(myList)
df['lower']=df[0].apply(lambda x: x.lower())
df.groupby('lower',sort=0)[0].first().tolist()

输出:

^{pr2}$

相关问题 更多 >