파이썬에서 숫자 목록과 부정적인 대응 항목을 생성하는 편리한 단일 라이너가 있습니까?
예를 들어 숫자 6 ~ 9와 -6 ~ -9의 목록을 생성한다고 가정 해보십시오.
내 현재 접근 방식은 다음과 같습니다
l = [x for x in range(6,10)]
l += [-x for x in l]
간단한 “한 줄짜리”는 다음과 같습니다.
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
그러나 두 개의 목록을 생성 한 다음 서로 결합하는 것은 불편 해 보입니다.
답변
순서가 중요한지 잘 모르겠지만 튜플을 만들어 목록 이해에 풀 수 있습니다.
nums = [y for x in range(6,10) for y in (x,-x)]
print(nums)
[6, -6, 7, -7, 8, -8, 9, -9]
답변
멋지고 읽기 쉬운 함수를 만듭니다.
def range_with_negatives(start, end):
for x in range(start, end):
yield x
yield -x
용법:
list(range_with_negatives(6, 10))
그것이 당신이 무엇이든 편리한 원 라이너를 얻는 방법입니다. 매직 프로 해커처럼 보이려고하지 마십시오.
답변
가장 간단한 해결책은 *
unpacking 연산자를 사용하여 두 범위를 목록으로 압축 해제하는 것입니다 .
>>> [*range(6, 10), *range(-9, -5)]
[6, 7, 8, 9, -9, -8, -7, -6]
이것은 가장 짧은 대답 일뿐 만 아니라 단일 목록 만 구성하고 두 개 이상의 함수 호출을 포함하지 않기 때문에 가장 성능이 range
좋습니다.
timeit
모듈을 사용 하여이 질문의 모든 답변을 테스트하여 이것을 확인했습니다 .
답변 ID 방법 시간 결과 -------------------------------------------------- ------------------------------------------------ (문제) [x 범위 (6,10)의 x에 대한 x] + [범위 범위의 y에 대한 y (-9, -5)] 루프 당 0.843 usec (이 답변) [* range (6, 10), * range (-9, -5)] 루프 당 0.509 usec 61348876 [범위 (x, -x)에서 y의 경우 (6,10)의 x에 대한 y] 루프 당 0.754 usec 61349149 list (range_with_negatives (6, 10)) 루프 당 0.795 usec 61348914 list (itertools.chain (range (6, 10), range (-9, -5))) 0.709 루프 당 usec 61366995 [itertools.product ((-1, 1), range (6, 10))의 부호 x, 부호 x x] 루프 당 0.899 usec 61371302 list (range (6, 10)) + list (range (-9, -5)) 루프 당 0.729 usec 61367180 list (range_with_negs (6, 10)) 루프 당 1.95 usec
(내 컴퓨터에서 Python 3.6.9를 사용하여 적시에 테스트 (평균 사양))
답변
itertools.chain()
두 범위를 연결하는 데 사용할 수 있습니다 .
import itertools
list(itertools.chain(range(6, 10), range(-9, -5)))
답변
itertools.product
직교 곱인을 사용할 수 있습니다 .
[sign*x for sign, x in product((-1, 1), range(6, 10))]
[-6, -7, -8, -9, 6, 7, 8, 9]
곱셈을 사용하기 때문에 속도가 느릴 수 있지만 읽기 쉬워야합니다.
순전히 기능적인 솔루션을 원한다면 다음 itertools.starmap
과 operator.mul
같이 가져올 수도 있습니다 .
from itertools import product, starmap
from operator import mul
list(starmap(mul, product((-1, 1), range(6, 10))))
그러나 이것은 읽기 어렵습니다.
답변
두 range
객체 를 결합하여 정말 가깝습니다 . 그러나 더 쉬운 방법이 있습니다.
>>> list(range(6, 10)) + list(range(-9, -5))
[6, 7, 8, 9, -9, -8, -7, -6]
즉, 각 range
개체를 목록으로 변환 한 다음 두 목록을 연결하십시오.
itertools를 사용하는 또 다른 접근법 :
>>> list(itertools.chain(range(6, 10), range(-9, -5)))
[6, 7, 8, 9, -9, -8, -7, -6]
itertools.chain()
일반화 된 것과 같습니다 +
: 두 개의 목록을 추가하는 대신 하나의 반복자를 연쇄 적으로 연결하여 “슈퍼 반복기”를 만듭니다. 그런 다음 그것을 전달 list()
하면 메모리에 원하는 모든 숫자가 포함 된 구체적인 목록이 나타납니다.
답변
또 다른 가능성으로 무게.
가독성을 원한다면 원래의 원 라이너는 꽤 좋았지 만 음수 범위가 덜 명확하다고 생각하는 것처럼 범위를 동일하게 변경합니다.
[x for x in range(6, 10)] + [-x for x in range(6, 10)]