2017-08-24 38 views
2

我想从python 3中的列表中选择与特定值匹配的条目。这应该导致两个列表:a带有所选条目的新列表以及没有它们的修改后的原始列表。通过选择具有特定值的条目将python 3列表中的字典拆分为两个的最有效方法

方案

假设我们有类型的字典列表:

import random, sys, time 

letters_1 = [] 
colors = ["red", "orange", "yellow", "green", "blue", "purple"] 
for i in range(100000): 
    letter = {"color": random.choice(colors), "content": random.randint(0, sys.maxsize)} 
    letters_1.append(letter) 
letters_2 = list(letters_1) 

我们要选择具有一定键一定值的所有类型的字典,将它们收集到一个新的列表,只留最初列表中的其他人。这与如何从实际的字母堆中选择所有红色字母相对应。

可能性

这可以通过列表理解或通过一个for循环来完成。

列表理解的问题是,每一个列表理解只创建一个列表。即为了做我们想做的事情,我们必须经历两次列表:首先将所选项目复制到新列表中,然后将选定项目移除到原始列表。要继续脚本:

time_0 = time.time() 
red_letters_1 = [letter for letter in letters_1 if letter["color"]=="red"] 
letters_1 = [letter for letter in letters_1 if letter["color"]!="red"] 
time_1 = time.time() 

for循环的问题是,它会导致更多的复杂代码,它(奇怪)需要更长的时间来执行:

time_2 = time.time() 
red_letters_2 = [] 
other_letters_2 = [] 
for letter in letters_2: 
    if letter["color"] == "red": 
     red_letters_2.append(letter) 
    else: 
     other_letters_2.append(letter) 
letters_2 = other_letters_2 
time_3 = time.time() 

print(time_1 - time_0) 
print(time_3 - time_2) 

输出:

0.011380434036254883 
0.015761613845825195 

注意:您可以删除需要第二个列表other_letters_2通过向后列出并使用pop(),但这需要更长的时间(实际上长10倍以上)。

问题

虽然有两个列表推导的可能性显然是最快的这些可能性,似乎低效做两个列表内涵。是否有可能把这个折叠成一个列表理解(不会使其效率低下)?还有另一种更有效的方法吗?还是有一个原因,为什么不可能通过两个列表解析来加速超越可能性?就相关问题

问题

注已建议是this thread, 重复,其中一个问题是关于选择使用列表理解列表的两个子集(或循环)。在这种情况下,唯一的方法是测试两种不同的条件,如this answer中所建议的,通过应用嵌套列表理解,可能会缩短一些可读性。由于(1)本建议副本的解决方案不适用于本问题和(2)(正如所指出的那样)。Kounis)目前的问题可能通过修改列表理解中的原始列表来允许不同的解决方案,我提交这不是重复的(在任何情况下都不是确切的)。我在问题开始时也澄清了这一点。

Python版本: 3.6.2

+0

*“与列表理解的问题是,每一个列表理解只创建一个列表“*。他们确实只创建一个,但在这样做时他们可以修改另一个,例如通过使用“pop”。例如.. –

+0

您是否100%确定这将在这样庞大的列表上被称为数百万次,速度提高将值得不太清晰/可维护代码的权衡?或者你只是在假设地提问? –

+0

我不认为这个问题是重复的。这里的OP想要修改最初的一个并创建一个新的。不是两个新的。 –

回答

1

如何:(我减少了样本规模测试,但你可以杀青它备份)

import random, sys 

letters_1 = [] 
colors = ["red", "orange", "purple"] 
for i in range(10): 
    letter = {"color": random.choice(colors), "content": random.randint(0, sys.maxsize)} 
    letters_1.append(letter) 

letters_1, letters_2 = [[x for x in letters_1 if x['color'] in i] for i in [('red',), ("orange", "purple")]] 

这是一个单一的列表理解利用可变的拆包。

让我知道这是如何执行比较。我很乐观。


正如你还会注意到,上面的代码不会修改原始,并创建一个新的,但创建了两个新的代替(覆盖原件)

+0

谢谢,这实际上是[其他线程的解决方案]的改编版本(https://stackoverflow.com/a/14100580/1735215)。令人惊讶的是,它比具有两个列表理解的列表慢:两个列表解析:'0.011686563491821289',For循环:'0.016497135162353516',嵌套列表理解('red_letters_4,letters_4 = [[x for letters_4如果x ['color' ]在我[]中为[(“红”),(“橙”,“黄”,“绿”,“蓝”,“紫”)]]):'0.014462709426879883' – 0range

相关问题