【问题标题】:Small loop of several huge nested loops vs huge loop of small nested loops performance?几个大嵌套循环的小循环与小嵌套循环的大循环性能?
【发布时间】:2019-11-13 11:45:48
【问题描述】:

我有一个服务器以多维数组的格式访问和获取数据,所以最终结果是:

 [
    [
        [n1t1:1, n1s1:2, n1o1:5],
        [n1t2:3, n1s2:8, n1o2:9]
    ],
    [
        [n2t1:9, n2s1:3, n2o1:2],
        [n2t2:5, n2s2:1, n2o2:7]
    ],
    [
        [n3t1:4, n3s1:9, n3o1:2],
        [n3t2:7, n3s2:1, n3o2:5]
    ]
 ]

我需要遍历该数组,仅访问 s1 值并将它们存储到一个新数组中,该数组将作为结果返回。

选项 1:

result = []
parent_enum = 0
while len(array) > parent_enum:
    child_enum = 0
    result.append([])
    while len(child_enum) > array_num:
        result[parent_enum].append(array[parent_enum][child_enum][1])
        child_enum += 1
    parent_enum += 1

选项 2:

result = [[] for i in range(len(array))]
parent_enum = 0
while len(array[0]) > parent_enum:
    child_enum = 0
    while len(array) > child_enum:
         result[child_enum].append(array[child_enum][parent_enum][1])
         child_enum += 1
    parent_enum += 1

有区别吗?如果有,哪种方式更高效、更快捷?考虑到第 2 维最大为 20,第 3 维最大为 500

【问题讨论】:

  • 1)我循环遍历数组,每行只访问 1 个值,而不是 3 个。2)较小的数组,较少的数据
  • 对于这样的问题,您可以在测试数据上使用timeit buitlin 模块来查看实际的运行时差异
  • 谢谢,有没有办法检查处理?还是不会引起注意?
  • 这两个“选项”看起来都不是最有效的
  • 使用 timeit 并注意两个代码 sn-ps 之间的时间差异通常可以很好地估计它们之间的 处理时间 差异。它还可能告诉您,两者之间几乎没有区别。另外值得注意的是,如果您对内存和函数调用的关注超过时间,并且如果您使用的是 ipython(或 jupyter),则可以使用prun 来分析代码

标签: python arrays performance loops


【解决方案1】:

为什么不使用简单的列表推导:

arr = [
    [
        ["n1t1:1", "n1s1:2", "n1o1:5"],
        ["n1t2:3", "n1s2:8", "n1o2:9"]
    ],
    [
        ["n2t1:9", "n2s1:3", "n2o1:2"],
        ["n2t2:5", "n2s2:1", "n2o2:7"]
    ],
    [
        ["n3t1:4", "n3s1:9", "n3o1:2"],
        ["n3t2:7", "n3s2:1", "n3o2:5"]
    ]
 ]


result = [[arr_lev3[1] for arr_lev3 in arr_lev2] for arr_lev2 in arr]

print(result)

示例输出:

[['n1s1:2', 'n1s2:8'], ['n2s1:3', 'n2s2:1'], ['n3s1:9', 'n3s2:1']]

而且比 map 方法快 2 倍以上:

In [38]: %timeit result = [[arr_lev3[1] for arr_lev3 in arr_lev2] for arr_lev2 in arr]
753 ns ± 2.24 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [39]: %timeit result2 = list(map(lambda first: list(map(lambda second: second[1], first)), arr))
1.63 µs ± 20.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

【讨论】:

  • 看起来很简单,非常感谢!跟进问题,您认为它比使用map()lambdas 更快/更有效吗?
  • @AdemirGotov,它肯定会击败map 方法
  • @AdemirGotov,不客气,请查看添加到答案的时间(纳秒/微秒)
【解决方案2】:

通过使用内置函数,以下代码应该更具可读性并且具有良好的性能。

data = [ ...your data... ]
result = map(lambda first:  # for each first-level entry
                 map(lambda second:  # for each second-level entry within first
                         second[1],  # return the second value
                     first
                 ),
             data
         )
[
    [
        2,
        8
    ],
    [
        3,
        1
    ],
    [
        9,
        1
    ]
 ]

【讨论】:

  • @AdemirGotov,你测试了吗?它会抛出一个错误。 map 函数签名是 map(function_to_apply, list_of_inputs)。这种方法将可迭代作为第一个参数传递
  • 对不起,这不是我的想法。换了顺序,概念还是一样。
猜你喜欢
  • 2020-05-30
  • 2019-03-08
  • 1970-01-01
  • 2016-09-18
  • 1970-01-01
  • 2021-01-21
  • 1970-01-01
  • 2016-05-13
  • 1970-01-01
相关资源
最近更新 更多