理解列表与for循环的复杂性

时间:2019-06-03 12:25:35

标签: python python-3.x

我在Python中有两种算法,可以将元组列表转换成字典:

  def _prep_high_low_data_for_view(self, low_high_list):
    dates = []
    prices = []
    lables = []
    for (x, y, z) in low_high_list:
        dates.append(x)
        prices.append(y)
        lables.append(z)

    return {'date': dates,
            'price': prices,
            'label': lables
            }

第二个是:

    def _prep_high_low_data_for_view(self, low_high_list):
    return {'date': [date for date, _, _ in low_high_list],
            'price': [price for _, price, _ in low_high_list],
            'label': [lable for _, _, lable in low_high_list],
            }

这两种算法在功能上是等效的。 是否存在第二种算法,因为存在三个单独的列表理解,因此第二种算法在复杂性方面更差吗?

3 个答案:

答案 0 :(得分:4)

您可以使用zip构建3个列表:

dates,prices,labels = zip(*low_high_list)

放在一行函数中:

def third_function(low_high_list):
    return dict.fromkeys(zip(["date","price","label"],zip(*low_high_list)))

平均而言,它比Florian_H中的second_function()运行得更快。

测试和结果:

def third_function(low_high_list):
    return dict.fromkeys(zip(["date","price","label"],zip(*low_high_list)))

def fourth_function(low_high_list):
    dates,prices,labels = zip(*low_high_list)
    return { "date":dates, "price":prices, "label":labels }


lst = [tuple(random.randint(0,100) for _ in range(3)) for i in range(10000)]

from timeit import timeit
count = 1000

t0 = timeit(lambda:first_function(lst), number=count)
print("first_function: ",f"{t0:.3f}","1x" )

t = timeit(lambda:second_function(lst), number=count)
print("second_function:",f"{t:.3f}",f"{t0/t:.1f}x" )

t = timeit(lambda:third_function(lst), number=count)
print("third_function: ",f"{t:.3f}",f"{t0/t:.1f}x" )

t = timeit(lambda:fourth_function(lst), number=count)
print("fourth_function:",f"{t:.3f}",f"{t0/t:.1f}x" )

# first_function:  1.338 1x
# second_function: 0.818 1.6x
# third_function:  0.426 3.1x
# fourth_function: 0.375 3.6x

答案 1 :(得分:3)

是,不是。

它基本上是O(n)O(3n)的比较,但是当处理复杂性时,O(3n)会缩短为O(n)

是的,这两种算法都具有O(n)的复杂性,但是第一个算法的运算量要少三倍。

答案 2 :(得分:1)

正如Markust Meskanen提到的那样,第一个算法应该快3倍(不太复杂),但是为什么不尝试一下呢?在这里,您的代码具有随机值和时间度量。

import random, datetime

def first_function(low_high_list):
    dates = []
    prices = []
    lables = []
    for (x, y, z) in low_high_list:
        dates.append(x)
        prices.append(y)
        lables.append(z)

    return {'date': dates,
            'price': prices,
            'label': lables
            }


def second_function(low_high_list):
    return {'date': [date[0] for date in low_high_list],
            'price': [price[1] for price in low_high_list],
            'label': [label[2] for label in low_high_list],
            }


def second_function(low_high_list):
    return {'date': [date[0] for date in low_high_list],
            'price': [price[1] for price in low_high_list],
            'label': [label[2] for label in low_high_list],
            }


lst = [[random.randint(0,100),random.randint(0,100),random.randint(0,100)] for i in range(10000)]

print("first_function:")
tmp = datetime.datetime.now()
first_function(lst)
print(datetime.datetime.now() - tmp)

print("\nsecond_function:")
tmp = datetime.datetime.now()
second_function(lst)
print(datetime.datetime.now() - tmp)

瞧,第二个功能比第一个功能快两倍...

[output]
first_function:
0:00:00.004001

second_function:
0:00:00.002001

看起来,即使第二个函数运行了三次而不是一次,在这种情况下,列表理解仍然是循环附加列表的两倍。

1000倍的平均速度仍然大约是其两倍:

0:00:00.002820
0:00:00.001568