source

목록 이해:각 항목에 대해 두 개 이상의 항목 반환

nicesource 2023. 10. 1. 19:31
반응형

목록 이해:각 항목에 대해 두 개 이상의 항목 반환

목록 이해에서 각 항목에 대해 2개 이상의 항목을 반품할 수 있습니까?

내가 원하는 것(예:

[f(x), g(x) for x in range(n)]

돌아와야 할[f(0), g(0), f(1), g(1), ..., f(n-1), g(n-1)]

그래서 이 코드 블록을 대체할 무언가가 있습니다.

result = list()
for x in range(n):
    result.add(f(x))
    result.add(g(x))

이중 목록 이해:

[f(x) for x in range(5) for f in (f1,f2)]

데모:

>>> f1 = lambda x: x
>>> f2 = lambda x: 10*x

>>> [f(x) for x in range(5) for f in (f1,f2)]
[0, 0, 1, 10, 2, 20, 3, 30, 4, 40]
>>> from itertools import chain
>>> f = lambda x: x + 2
>>> g = lambda x: x ** 2
>>> list(chain.from_iterable((f(x), g(x)) for x in range(3)))
[2, 0, 3, 1, 4, 4]

타이밍:

from timeit import timeit

f = lambda x: x + 2
g = lambda x: x ** 2

def fg(x):
    yield f(x)
    yield g(x)

print timeit(stmt='list(chain.from_iterable((f(x), g(x)) for x in range(3)))',
             setup='gc.enable(); from itertools import chain; f = lambda x: x + 2; g = lambda x: x ** 2')

print timeit(stmt='list(chain.from_iterable(fg(x) for x in range(3)))',
             setup='gc.enable(); from itertools import chain; from __main__ import fg; f = lambda x: x + 2; g = lambda x: x ** 2')

print timeit(stmt='[func(x) for x in range(3) for func in (f, g)]',
             setup='gc.enable(); f = lambda x: x + 2; g = lambda x: x ** 2')


print timeit(stmt='list(chain.from_iterable((f(x), g(x)) for x in xrange(10**6)))',
             setup='gc.enable(); from itertools import chain; f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)

print timeit(stmt='list(chain.from_iterable(fg(x) for x in xrange(10**6)))',
             setup='gc.enable(); from itertools import chain; from __main__ import fg; f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)

print timeit(stmt='[func(x) for x in xrange(10**6) for func in (f, g)]',
             setup='gc.enable(); f = lambda x: x + 2; g = lambda x: x ** 2',
             number=20)

2.69210777094

3.13900787874

1.62461071932

25.5944058287

29.2623711793

25.7211849286

sum( ([f(x),g(x)] for x in range(n)), [] )

이는 다음과 같습니다.[f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...

다음과 같이 생각할 수도 있습니다.

def flatten(list):
    ...

flatten( [f(x),g(x)] for x in ... )

참고: 올바른 방법은 다음을 사용하는 것입니다.itertools.chain.from_iterable또는 이중 목록 이해.(모든 +의 목록을 다시 만들 필요가 없으므로 O(N^2) 성능이 아닌 O(N) 성능을 갖습니다.)계속 쓸게요.sum(..., [])빠른 원-라이너를 원하거나 급할 때, 또는 조합되는 항의 수가 제한되어 있을 때(예: <= 10).그것이 제가 아직도 여기서 이 주의사항을 언급하는 이유입니다.튜플을 사용할 수도 있습니다.((f(x),g(x)) for ...), ()(또는 khachik의 코멘트에 따라, 2개의 tup을 산출하는 발전기 fg(x))를 갖습니다.)

OP가 목록 이해 솔루션을 찾고 있다는 것을 알고 있지만 다음을 사용하여 대안을 제시하고자 합니다.list.extend().

f = lambda x: x
g = lambda x: 10*x

result = []
extend = result.extend
for x in range(5):
    extend((f(x),g(x)))

이중 목록 이해를 사용하는 것보다 약간 빠릅니다.

nums = range(100000)

def double_comprehension():
    return [func(x) for x in nums for func in (f,g)]

def list_extend():
    result = []
    extend = result.extend
    for x in nums:
        extend((f(x),g(x)))
    return result

%timeit -n100 double_comprehension()
23.4 ms ± 67 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit -n100 list_extend()
20.5 ms ± 213 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

파이썬 버전: 3.8.0

이 람다 함수는 두 개의 목록을 하나로 압축합니다.

zipped = lambda L1, L2: [L[i] 
                         for i in range(min(len(L1), len(L2))) 
                         for L in (L1, L2)]

예:

>>> f = [x for x in range(5)]
>>> g = [x*10 for x in range(5)]
>>> zipped(f, g)
[0, 0, 1, 10, 2, 20, 3, 30, 4, 40]

축소를 사용한 솔루션:

from functools import reduce

f    = lambda x: f"f({x})" ## Just for example
g    = lambda x: f"g({x})"
data = [1, 2, 3]

reduce(lambda acc, x: acc + [f(x), g(x)], data, [])
# => ['f(1)', 'g(1)', 'f(2)', 'g(2)', 'f(3)', 'g(3)']

이것이 문제에 접근하는 기능적인 방법입니다.리스트 이해는 본질적으로 다른 방법입니다.map데이터를 넘겨야 하지만 입력과 출력 사이에 일대일 매핑이 되지 않는 이 경우와 같은 경우에는reduce출력을 생성하는 방법에 대해 약간의 자유 재량권을 허용합니다.

일반적으로 아무for양식 구현:

result = []
for n in some_data:
  result += some_operation()
  ## etc.

(즉, 리스트 또는 유사한 데이터 구조에 부작용을 발생시키는 루프의 경우, 누적기 패턴)

선언문으로 리팩터링할 수 있음map/reduce/filter실행.

합리적으로 가능하다면 두 가지를 사용하는 것보다 사용하는 것을 선호해야 합니다.for일람표의 절Google Python Style Guide와 같은 일부 스타일 가이드는 여러 개를 사용하는 것을 금지합니다.for일람표의 절이 방법을 명시적으로 금지하지 않은 스타일 가이드를 사용할 수도 있지만, 다음과 같은 작업을 수행하면 이해력을 더욱 간결하게 만들 수 있습니다.

from itertools import product

result = [y(x) for y, x in product(range(n), (f, g))]

세상에, 비탄!왜 이 모든 양고기들, 납작한 것들, 지퍼들, 그리고 셈들?이것이 가장 간단하고 읽을 수 있는 것이 아닌가요?

>>> [v
...  for x in range(5)
...      for v in (2 * x,
...                2 * x + 1)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

두 ()로.f(x)그리고.g(x) (든)

언급URL : https://stackoverflow.com/questions/11868964/list-comprehension-returning-two-or-more-items-for-each-item

반응형