【问题标题】:Possible to compress into a dictionary comprehension?可以压缩成字典理解吗?
【发布时间】:2014-01-08 00:19:10
【问题描述】:
index = [x for x in range(0,81)]
membership_columns = {
    'column_0': index[0:81:9]
    'column_1': index[1:81:9]
    'column_2': index[2:81:9]
    'column_3': index[3:81:9]
    'column_4': index[4:81:9]
    'column_5': index[5:81:9]
    'column_6': index[6:81:9]
    'column_7': index[7:81:9]
    'column_8': index[8:81:9]
    }

是否可以将其压缩到字典理解中?另外,第 1 行的列表理解是否必要?我不确定如何将每个键本身变成列表理解。

【问题讨论】:

    标签: python list-comprehension dictionary-comprehension


    【解决方案1】:

    绝对有可能。我建议这样做:

    {('column_%d' % i): index[i:81:9] for i in xrange(9)}
    

    同样,第一个列表理解并不像刚刚那样需要:

    index = range(0,81)
    

    会完成同样的事情。

    您还可以将所有列表切片替换为 xrange,这只会生成您需要的值。你可以这样做:

    {('column_%d' % i): range(i,81, 9) for i in xrange(9)}
    

    因为 python 中的 range 函数需要一个 step 参数。见the docs.

    也就是说,尽管这看起来更优雅,但您确实会在切片方面受到性能打击,如果使用更大的理解,可能会变得更糟。在这个尺寸下,它并不是很明显:

    import timeit
    >>> timeit.timeit("{('column_%d' % i): range(i,81, 9) for i in xrange(9)}", number = 100000)
    1.3790168762207031
    >>> timeit.timeit("index=range(0,81);{('column_%d' % i): index[i:81:9] for i in xrange(9)}", number = 100000)
    1.1949927806854248
    

    显然这里的字符串格式比我想象的要慢。正如 martineau 所指出的,您可以使用串联来显着提高速度:

    >>> timeit.timeit("{('column_' + str(i)): range(i,81,9) for i in xrange(9)}", number = 100000)
    0.914525032043457
    

    但是随着i 的值较大,它开始变得相当大:

    >>> timeit.timeit("{('column_%d' % i): range(i,81, 9) for i in xrange(90)}", number = 100000)
    12.220430135726929
    >>> timeit.timeit("index=range(0,81);{('column_%d' % i): index[i:81:9] for i in xrange(90)}", number = 100000)
    9.669343948364258
    >>> timeit.timeit("index=range(0,81);{('column_' + str(i)): index[i:81:9] for i in xrange(90)}", number = 100000)
    7.163957118988037
    

    【讨论】:

    • 非常感谢。后续问题:索引切片是绝对必要的,还是有一个列表理解可以做同样的事情?
    • @TravM 其实你可以直接使用 range 来处理这种事情。查看更新的答案。
    • 通过不浪费所有空间来构建索引数组来平衡切片对性能的影响——并且在 非常 大尺寸下,理解可能再次开始变得更快,因为你还避免所有这些缓存未命中(以及,在非常大的尺寸下,页面未命中)。但无论如何,我认为你是对的,优雅可能比性能更重要。
    • timeit.timeit("{('column_' + str(i)): range(i,81,9) for i in xrange(9)}", number = 100000) 似乎快一点。
    • @martineau 哇!我不知道字符串格式化这么慢。已更新。
    猜你喜欢
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多