首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据嵌套列表中的元素删除列表的重复项

如何根据嵌套列表中的元素删除列表的重复项
EN

Stack Overflow用户
提问于 2020-01-27 11:46:35
回答 3查看 287关注 0票数 0

我想从列表中删除重复的内容。对于嵌套列表中的每个第二个元素,第一个元素并不总是唯一的。第一个值对于整个列表是唯一的。这些数字在整个列表中只出现一次,但没有排序。

代码语言:javascript
运行
复制
my_list = [[4, 'C'], [1, 'A'], [3, 'B'], [2, 'A'], [5, 'C']]

删除重复项是基于嵌套列表中的第二个元素。我需要每个唯一的第二个元素的最小值,例如:

代码语言:javascript
运行
复制
my_unique_list = [[1, 'A'], [3, 'B'], [4, 'C']]

不管输出的顺序是什么。

因此,选择用于1'A' (as 1低于[2, 'A']的2)、3'B' ('B'没有其他值)和'C'4 (as 4小于5,来自[5, 'C'])。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-01-27 11:53:42

使用字典将唯一的字母(第二个值)映射为每个字母的最小值,然后简单地将该字典中的[value, key]对作为输出:

代码语言:javascript
运行
复制
minimi = {}
inf = float('inf')
for val, key in my_list:
    # float('inf') as default value is always larger, so val is picked
    # if the key isn't present yet.
    minimi[key] = min(val, minimi.get(key, inf))

my_unique_list = [[v, k] for k, v in minimi.items()]

通过使用字典作为中介,您可以在线性时间内过滤输入。

演示:

代码语言:javascript
运行
复制
>>> my_list = [[4, 'C'], [1, 'A'], [3, 'B'], [2, 'A'], [5,'C']]
>>> minimi, inf = {}, float('inf')
>>> for val, key in my_list:
...     minimi[key] = min(val, minimi.get(key, inf))
...
>>> minimi
{'C': 4, 'A': 1, 'B': 3}
>>> my_unique_list = [[v, k] for k, v in minimi.items()]
>>> my_unique_list
[[4, 'C'], [1, 'A'], [3, 'B']]

你为什么要关心跑步时间?因为随着输入的增加,运行时间也增加了。对于需要O(N^2) (二次)时间的方法,当您从1000项增加到100万项(是大小的1000倍)时,您的运行时间将增加100万倍!对于O(N logN)方法(使用排序的方法),运行时间将增加2000倍,而上述线性方法将花费1000倍的时间,与输入规模成线性关系。

对于大的输入,这可以使‘花费一两个小时’到‘花费数百万年’之间的差别。

以下是这种方法与扎米尔的排序和集合方法(O(N logN))以及TJC World's Pandas方法(也是O(N LogN))之间的时间试验比较:

代码语言:javascript
运行
复制
from string import ascii_uppercase
from functools import partial
from timeit import Timer
import random
import pandas as pd

def gen_data(N):
    return [[random.randrange(1_000_000), random.choice(ascii_uppercase)] for _ in range(N)]

def with_dict(l, _min=min, _inf=float('inf')):
    minimi = {}
    m_get = minimi.get
    for val, key in l:
        minimi[key] = _min(val, m_get(key, _inf))
    return [[v, k] for k, v in minimi.items()]

def with_set_and_sort(l):
    already_encountered = set()
    ae_add = already_encountered.add
    return [i for i in sorted(l) if i[1] not in already_encountered and not ae_add(i[1])]

def with_pandas(l):
    return (
        pd.DataFrame(l)
        .sort_values(by=0)
        .drop_duplicates(1)
        .to_numpy()
        .tolist()
    )

for n in (100, 1000, 10_000, 100_000, 1_000_000):
    testdata = gen_data(n)
    print(f"{n:,} entries:")
    for test in (with_dict, with_set_and_sort, with_pandas):
        count, total = Timer(partial(test, testdata)).autorange()
        print(f"{test.__name__:>20}: {total/count * 1000:8.3f}ms")
    print()

我已经使用了我所知道的所有小性能技巧;通过将全局和属性缓存在循环之外的本地名称中,避免了对全局和属性的重复查找。

这一产出如下:

代码语言:javascript
运行
复制
100 entries:
           with_dict:    0.028ms
   with_set_and_sort:    0.032ms
         with_pandas:    2.070ms

1,000 entries:
           with_dict:    0.242ms
   with_set_and_sort:    0.369ms
         with_pandas:    2.312ms

10,000 entries:
           with_dict:    2.331ms
   with_set_and_sort:    5.639ms
         with_pandas:    5.476ms

100,000 entries:
           with_dict:   23.105ms
   with_set_and_sort:  127.772ms
         with_pandas:   40.330ms

1,000,000 entries:
           with_dict:  245.982ms
   with_set_and_sort: 2494.305ms
         with_pandas:  578.952ms

因此,只有100个输入,排序方法看起来可能是同样快(几毫秒不同的方式),但随着投入的增长,这种方法失去了一个加速的步伐。

熊猫在这里的各个方面都输掉了。Dataframes是一个很好的工具,但在这里却是错误的工具。它们是庞大的数据结构,因此对于小输入,它们的高开销使它们处于毫秒范围内,远远落后于其他两个选项。在10k条目时,它开始超越排序和集方法,但是即使数据操作高度优化,具有更大输入的排序运行时的增长仍然不能超过线性方法。

票数 9
EN

Stack Overflow用户

发布于 2020-01-27 12:03:58

代码语言:javascript
运行
复制
already_encountered = set()
my_new_list = [i for i in sorted(my_list) if i[1] not in already_encountered and not already_encountered.add(i[1])]

输出:

代码语言:javascript
运行
复制
[[1, 'A'], [3, 'B'], [4, 'C']]
票数 1
EN

Stack Overflow用户

发布于 2020-01-27 11:57:07

利用大熊猫;

代码语言:javascript
运行
复制
>>> import pandas as pd
>>> my_list = [[1, 'A'], [2, 'A'], [3, 'B'], [4, 'C'], [5,'C']]
>>> df = pd.DataFrame(my_list)
>>> df.sort_values(by = 0).drop_duplicates(1).to_numpy().tolist()
[[1, 'A'], [3, 'B'], [4, 'C']]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59930540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档