Я тестировал большинство предлагаемых решений с помощью perfplot (мой собственный проект, по существу, обертка вокруг timeit
) и нашел
list(itertools.chain.from_iterable(a))
самым быстрым решением (если более 10 списков объединены).
Код для воспроизведения графика:
import functools
import itertools
import numpy
import operator
import perfplot
def forfor(a):
return [item for sublist in a for item in sublist]
def sum_brackets(a):
return sum(a, [])
def functools_reduce(a):
return functools.reduce(operator.concat, a)
def itertools_chain(a):
return list(itertools.chain.from_iterable(a))
def numpy_flat(a):
return list(numpy.array(a).flat)
def numpy_concatenate(a):
return list(numpy.concatenate(a))
perfplot.show(
setup=lambda n: [list(range(10))] * n,
kernels=[
forfor, sum_brackets, functools_reduce, itertools_chain, numpy_flat,
numpy_concatenate
],
n_range=[2**k for k in range(16)],
logx=True,
logy=True,
xlabel='num lists'
)
Самый простой подход - это, вероятно, сохранение некоторого внешнего состояния и реализация f влияет на его содержимое.
(define x 0)
(define (f n) (let ((tmp x)) (set! x n) tmp))
Таким образом, x изначально 0, и каждый вызов f возвращает текущее значение x и сохранить аргумент как новое значение x. Таким образом, (f 0), за которым следует (f 1), оба возвращают 0, оставляя окончательное значение x равным 1. При оценке (f 1), за которой следует (f 0), будет 0, а затем 1 с конечным x из 0.
С помощью call / cc .
(define (f)
(call/cc
(lambda (c) (+ (c 0) (c 1)))))
(write (f))
Вызов c внутри любого аргумента в +
приводит к немедленному возврату f
, давая 0 или 1, в зависимости от того, какой аргумент сначала оценивается.
Но я подозреваю, что он всегда будет оценивать слева направо и, следовательно, возвращает 0.