programing

Python을 사용하여 목록의 값 바꾸기

goodsources 2023. 4. 16. 15:00
반응형

Python을 사용하여 목록의 값 바꾸기

값을 None으로 치환하는 리스트가 있습니다.여기서 condition()은 True를 반환합니다.

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

예를 들어 조건 체크 bool(항목%2)이 반환되어야 하는 경우:

[None, 1, None, 3, None, 5, None, 7, None, 9, None]

이를 위한 가장 효율적인 방법은 무엇입니까?

목록 이해 기능을 사용하여 새 목록을 작성합니다.

new_items = [x if x % 2 else None for x in items]

필요에 따라 원래 목록을 변경할 수 있지만, 실제로 시간이 절약되지는 않습니다.

items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for index, item in enumerate(items):
    if not (item % 2):
        items[index] = None

다음은 비타임세이브를 나타내는 (Python 3.6.3) 타이밍입니다.

In [1]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: for index, item in enumerate(items):
   ...:     if not (item % 2):
   ...:         items[index] = None
   ...:
1.06 µs ± 33.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [2]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: new_items = [x if x % 2 else None for x in items]
   ...:
891 ns ± 13.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Python 2.7.6 타이밍:

In [1]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: for index, item in enumerate(items):
   ...:     if not (item % 2):
   ...:         items[index] = None
   ...: 
1000000 loops, best of 3: 1.27 µs per loop
In [2]: %%timeit
   ...: items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   ...: new_items = [x if x % 2 else None for x in items]
   ...: 
1000000 loops, best of 3: 1.14 µs per loop
ls = [x if (condition) else None for x in ls]

또 다른 방법이 있습니다.

>>> L = range (11)
>>> map(lambda x: x if x%2 else None, L)
[None, 1, None, 3, None, 5, None, 7, None, 9, None]

OP가 코멘트로 던진 부질없는 질문에 대해 설명합니다.

리스트가 아닌 범위(11)의 값을 산출하는 제너레이터가 있는 경우.제너레이터의 값을 바꿀 수 있습니까?

네, 아주 쉬워요:

def replaceiniter(it, predicate, replacement=None):
  for item in it:
    if predicate(item): yield replacement
    else: yield item

첫 번째 arg로 반복 가능한 값(제너레이터 호출 결과 포함)을 전달하고, 두 번째 arg로 값을 대체할 필요가 있는지 여부를 결정하는 술어를 전달하고, 'er'를 rip합니다.

예를 들어 다음과 같습니다.

>>> list(replaceiniter(xrange(11), lambda x: x%2))
[0, None, 2, None, 4, None, 6, None, 8, None, 10]
>>> L = range (11)
>>> [ x if x%2 == 1 else None for x in L ]
[None, 1, None, 3, None, 5, None, 7, None, 9, None]

적절한 값을 바꾸려는 경우 원본의 전체 슬라이스에 할당하여 목록 이해의 값으로 원본 목록을 업데이트할 수 있습니다.

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
id_before = id(data)
data[:] = [x if x % 2 else None for x in data]
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: True

예를 들어, 원본 목록을 가리키는 이름이 여러 개 있는 경우data2=data목록을 변경하기 전에 할당하기 위한 슬라이스 표기법을 건너뜁니다.data,data새로 작성된 목록을 가리키기 위해 재바인드합니다.data2는 원래 변경되지 않은 목록을 계속 가리킵니다.

data = [*range(11)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
data2 = data
id_before = id(data)
data = [x if x % 2 else None for x in data]  # no [:] here
data
# Out: [None, 1, None, 3, None, 5, None, 7, None, 9, None]
id_before == id(data)  # check if list is still the same
# Out: False
data2
# Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

주의: 이것은 일반적으로 다른 것(목록 변경 여부)보다 하나를 선호하는 경우에는 권장되지 않지만 주의해야 할 동작입니다.

이게 도움이 될지도...

test_list = [5, 8]
test_list[0] = None
print test_list
#prints [None, 8]

언급URL : https://stackoverflow.com/questions/1540049/replace-values-in-list-using-python

반응형