【问题标题】:python optimise a nested for loop with appendpython用追加优化嵌套for循环
【发布时间】:2018-06-23 23:04:39
【问题描述】:

我有 2 个 for 循环,主要用于处理大量数据。我想对此进行优化并尽可能提高速度。

source = [['row1', 'row2', 'row3'],['Product', 'Cost', 'Quantity'],['Test17', '3216', '17'], ['Test18' , '3217' , '18' ], ['Test19', '3218', '19' ], ['Test20', '3219', '20']]

创建一个生成器对象

it = iter(source)
variables = ['row2', 'row3']
variables_indices = [1, 2]
getkey = rowgetter(*key_indices)
for row in it:
    k = getkey(row)
    for v, i in zip(variables, variables_indices):
        try:
            o = list(k)  # populate with key values initially
            o.append(v)  # add variable
            o.append(row[i]) # add value
            yield tuple(o)
        except IndexError:
            pass

def rowgetter(*indices):
    if len(indices) == 0:
        #print("STEP 7")
        return lambda row: tuple()
    elif len(indices) == 1:
        #print("STEP 7")
        # if   only one index, we cannot use itemgetter, because we want a
        # singleton sequence to be returned, but itemgetter with a single
        # argument returns the value itself, so let's define a function
        index = indices[0]
        return lambda row: (row[index],) 

    else:

        return operator.itemgetter(*indices)

这将返回一个元组,但对于 100,000 行(源在示例中有 5 行)平均 100 秒要花费很多时间。任何人都可以帮助减少这个时间。

注意:我还尝试了内联循环和列表理解,但每次迭代都不会返回

【问题讨论】:

  • 请将source 修复为真正有效的python。 getkey 还有什么作用?你为什么使用iteri 来自哪里?我们真的需要一个完整的工作示例!
  • @match 我现在用完整的例子编辑了我的问题
  • 还不清楚i是什么?
  • 是内部的fr循环索引

标签: python python-3.x for-loop nested-loops


【解决方案1】:

下面标记了一些改进,但它们不会改变算法的复杂性:

zipped = list(zip(variables, variables_indices))  # create once and reuse

for row in it:
    for v in zipped:
        try:
            yield (*getkey(row), v, row[i])  # avoid building list and tuple conversion 
        except IndexError:
            pass

【讨论】:

  • yield (*k, v, row[i]) 仅适用于 python 3.5 (3.6?) 及更高版本。
  • @Jean-FrançoisFabre 它确实适用于 Python 3.5。我将把它留在那里,因为问题被标记为Python-3.x
  • @schwobaseggl 是的,如果它与 python 3.5 及更高版本一起工作就可以了,但时间并没有减少,因为仍然有 2 个 for 循环
【解决方案2】:

k 创建一个list 然后附加2 个项目然后转换为tuple 会创建很多副本。

我会建议一个带有生成器的辅助函数从k 列表中产生,然后产生剩余的元素。将其包装在 tuple 中以创建一个随时可用的函数:

k = [1,2,3,4]

def make_tuple(k,a,b):
    def gen(k,a,b):
        yield from k
        yield a
        yield b
    return tuple(gen(k,a,b))

result = make_tuple(k,12,14)

输出:

(1, 2, 3, 4, 12, 14)

【讨论】:

  • 我假设我必须在嵌套的 for 循环中调用此函数,但所花费的时间仍然是原始时间的 2 倍。我想减少时间
  • 您的 minimal reproducible example 不能按原样完全运行,您能否创建 1 个在您的真实代码之外运行的代码块,以便我们更好地查看?
  • 另外,你真的需要tuple吗?
猜你喜欢
  • 2017-05-28
  • 2012-01-27
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多