목록 이해의 각 항목에 대해 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))
목록 이해의 각 항목에 대해 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))
답변:
>>> 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
(f(x), g(x))
합니다. 다음과 같이 더 잘 작성할 수 있습니다 def fg(x): yield x + 2; yield x ** 2; list(chain.from_iterable(fg(x) for x in range(3)))
..
chain.from_iterable((func(x) for func in funcs) for x in range(n)))
. 우연히 khachik의 불만을 제거합니다. (어떤 의미에서 나와 그의 프로세스는 본질적으로 동일합니다. 단순히 내부 생성기를 다르게 정의합니다.)
sum(..., [])
모든 +에 대한 목록을 다시 만들 필요가 없기 때문에 내 대답 보다 낫습니다 (따라서 O (N ^ 2) 성능이 아닌 O (N) 성능이 있습니다). 나는 아직도 사용합니다 sum(..., [])
나는 빠른 한 - 라이너를 원하거나 내가 서둘러 해요, 또는 결합 된 용어의 수는 경계 할 때 (예를 들어 <= 10) 때.
[y for x in range(n) for y in (f(x), g(x))]
그러나 이것은 아마도 더 느릴 것입니다. @jamylak 원한다면 이것도 테스트 할 수 있습니다.
이중 목록 이해 :
[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]
for x in range(5): for f in (f1, f2): newlist.append(f(x))
. 나는 계속해서 순서를 뒤집으려고 노력했기 때문에 조금 혼란스러워했습니다.
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 ...), ()
.
[f(1),g(1)] + [f(2),g(2)] + [f(3),g(3)] + ...
sum()
이런 식으로 남용 하는 것을 반 패턴이라고 생각하며 어떤 상황에서든 그것을 사용할 이유가 없다고 생각합니다. 다른 답변의 코드는 타이핑이 적기 때문에 "빠른 한 줄짜리를 원하거나 서둘러 할 때"라는 변명조차도 실제로 그것을 자르지 않습니다.
OP가 목록 이해 솔루션을 찾고 있다는 것을 알고 있지만 .NET을 사용하는 대안을 제공하고 싶습니다 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)
Python 버전 : 3.8.0
reduce를 사용하는 솔루션 :
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.
(즉, 목록 또는 유사한 데이터 구조에 부작용을 일으키기위한 for 루프)
선언적 map/reduce/filter
구현 으로 리팩토링 할 수 있습니다 .