【问题标题】:Python - remove duplicates from list with different suffixesPython - 从具有不同后缀的列表中删除重复项
【发布时间】:2018-04-05 15:33:42
【问题描述】:

我有:

['asdf/ws', 'abc/abc/', 'asdf/wss', 'asdf/', 'ab/wss', 'ab/ws', 'abc/abc/ws', 'xyz/wss']

我需要:

['asdf/ws', 'abc/abc/', 'ab/wss', 'xyz/wss']

可能的后缀是:

/
/ws
/wss
  • 前缀可以是任意字符串
  • 前缀将包含未指定数量的附加正斜杠
  • 将选择列表中从左侧算起的第一个唯一前缀项。

应用程序正在 ping websockets 并返回一个具有最低延迟的连接列表,但不知道每个套接字的哪个后缀是正确的。有些套接字允许多个后缀,有些只允许一种类型。有时套接字的管理员会更改所需的后缀,恕不另行通知。一旦每个套接字返回 ping,列表就会按延迟排序,但是我有需要删除的重复项。

通常,要删除列表中的重复项,我会这样做:

list(set(my_List))

但这在这里不起作用

【问题讨论】:

    标签: python list sorting set


    【解决方案1】:
    lst = ['asdf/ws', 'abc/abc/', 'asdf/wss', 'asdf/', 'ab/wss', 'ab/ws', 'abc/abc/ws', 'xyz/wss']
    
    # use a set to cache duplicates
    caches = set()
    results = []
    
    for item in lst:
    
        prefix = item.rsplit('/', 2)[0]
    
        # check whether prefix already exists
        if prefix not in caches:
    
            results.append(item)
            caches.add(prefix)
    
    results
    # ['asdf/ws', 'abc/abc/', 'ab/wss', 'xyz/wss']
    

    【讨论】:

    • 我接受这是最好的,因为它是最易读的解决方案,而且这是面向非专业用户的公共财务软件;可读性很重要。但是我认为 item.rsplit('/', 2)[0] 是错误的;我正在使用 item.rsplit('/', 1)[0]
    【解决方案2】:

    您可以使用enumerate 检查是否已发现任何前缀,即返回的 ping 响应中是否存在具有相同前缀的连接:

    import re
    s = ['asdf/ws', 'abc/abc/', 'asdf/wss', 'asdf/', 'ab/wss', 'ab/ws', 'abc/abc/ws', 'xyz/wss']
    new_s = [a for i, a in enumerate(s) if not any(re.findall('^[a-zA-Z]+', a)[0] == re.findall('^[a-zA-Z]+', c)[0] for c in s[:i])]
    

    输出:

    ['asdf/ws', 'abc/abc/', 'ab/wss', 'xyz/wss']
    

    【讨论】:

    • 使用正则表达式来完成这项任务非常优雅,而且是正确的方法。这应该是问题的正确答案。
    • @pythonic833 谢谢:)
    【解决方案3】:

    首先我们只提取具有所需后缀的元素(结束忽略重复,注意这可能会改变顺序!)

    proc1= list(set([x for x in test if x.endswith('/') or x.endswith('/ws') or x.endswith('/wss')]))
    

    在下一步中,我们使用两个列表。一个用于存储已包含的前缀,另一个用于存储所需的元素。如果已经使用了前缀,则不要包含具有此前缀的元素并检查下一个。

    proc_f = []
    proc_suff = []
    for x in proc1:
        if x.split("/")[0] not in proc_suff:
            proc_suff.append(x.split("/")[0])
            proc_f.append(x)
    
    prof_f
    ['ab/ws', 'asdf/wss', 'abc/abc/ws', 'xyz/wss']
    

    【讨论】:

    • 非常好的答案! +1
    • 这没有返回正确的结果;例如应该是 ab/wss;有时两者中的一个具有显着不同的延迟,因为它重定向到另一个。
    • 好吧,因为我转换为 set() 元素的顺序发生了变化。如果这很重要,我会改变它
    【解决方案4】:

    你可以试试dict方法:

    data=['asdf/ws', 'abc/abc/', 'asdf/wss', 'asdf/', 'ab/wss', 'ab/ws', 'abc/abc/ws', 'xyz/wss']
    
    unique_items={}
    for i in data:
        data_suffic=i.split('/')
        if data_suffic[0] not in unique_items:
            unique_items[data_suffic[0]]="/".join(data_suffic)
    
    print(unique_items.values())
    
    ['abc/abc/', 'asdf/ws', 'ab/wss', 'xyz/wss']
    

    已更新以保持订单:

    data=['asdf/ws', 'abc/abc/', 'asdf/wss', 'asdf/', 'ab/wss', 'ab/ws', 'abc/abc/ws', 'xyz/wss']
    
    unique_items={}
    for j,i in enumerate(data):
        data_suffic=i.split('/')
        if data_suffic[0] not in unique_items:
            unique_items[data_suffic[0]]=(j,"/".join(data_suffic))
    
    print(list(map(lambda x:x[1],sorted(unique_items.values(),key=lambda x:x[0]))))
    

    输出:

    ['asdf/ws', 'abc/abc/', 'ab/wss', 'xyz/wss']
    

    【讨论】:

    • 不幸的是,这会丢失列表的延迟排序顺序
    • @litepresence 现在以正确的顺序返回。
    猜你喜欢
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2013-08-03
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多