Python 목록에서 조건과 일치하는 처음 N 개 항목 제거
함수가있는 경우 해당 조건과 일치하는 Python 목록에서 matchCondition(x)
첫 번째 n
항목을 제거하려면 어떻게 해야합니까?
한 가지 해결책은 각 항목을 반복하고 삭제 표시 (예 :로 설정 None
) 한 다음 이해력으로 목록을 필터링하는 것입니다. 이렇게하려면 목록을 두 번 반복하고 데이터를 변경해야합니다. 이를 수행하는 더 관용적이거나 효율적인 방법이 있습니까?
n = 3
def condition(x):
return x < 5
data = [1, 10, 2, 9, 3, 8, 4, 7]
out = do_remove(data, n, condition)
print(out) # [10, 9, 8, 4, 7] (1, 2, and 3 are removed, 4 remains)
itertools.filterfalse
및 사용하는 한 가지 방법 itertools.count
:
from itertools import count, filterfalse
data = [1, 10, 2, 9, 3, 8, 4, 7]
output = filterfalse(lambda L, c=count(): L < 5 and next(c) < 3, data)
그러면 다음 list(output)
이 제공됩니다.
[10, 9, 8, 4, 7]
반복 가능, 조건 및 삭제할 양을 취하는 생성기를 작성하십시오. 데이터를 반복하고 조건을 충족하지 않는 항목을 산출합니다. 조건이 충족되면 카운터를 증가시키고 값을 산출하지 마십시오. 카운터가 드롭하려는 양에 도달하면 항상 아이템을 양보하십시오.
def iter_drop_n(data, condition, drop):
dropped = 0
for item in data:
if dropped >= drop:
yield item
continue
if condition(item):
dropped += 1
continue
yield item
data = [1, 10, 2, 9, 3, 8, 4, 7]
out = list(iter_drop_n(data, lambda x: x < 5, 3))
이것은 목록의 추가 사본이 필요하지 않으며 목록을 한 번만 반복하고 각 항목에 대해 한 번만 조건을 호출합니다. 실제로 전체 목록을보고 싶지 않으면 list
결과 에서 호출을 중단 하고 반환 된 생성기를 직접 반복합니다.
받아 들여진 대답은 내 취향에 비해 너무 마술 적이었습니다. 다음은 흐름이 좀 더 명확 해지기를 바랍니다.
def matchCondition(x):
return x < 5
def my_gen(L, drop_condition, max_drops=3):
count = 0
iterator = iter(L)
for element in iterator:
if drop_condition(element):
count += 1
if count >= max_drops:
break
else:
yield element
yield from iterator
example = [1, 10, 2, 9, 3, 8, 4, 7]
print(list(my_gen(example, drop_condition=matchCondition)))
davidism 답변의 논리와 비슷 하지만 모든 단계에서 드롭 수를 초과 하는지 확인하는 대신 나머지 루프를 단락시킵니다.
참고 :yield from
사용할 수 없는 경우 에서 나머지 항목에 대해 다른 for 루프로 바꾸십시오 iterator
.
돌연변이가 필요한 경우 :
def do_remove(ls, N, predicate):
i, delete_count, l = 0, 0, len(ls)
while i < l and delete_count < N:
if predicate(ls[i]):
ls.pop(i) # remove item at i
delete_count, l = delete_count + 1, l - 1
else:
i += 1
return ls # for convenience
assert(do_remove(l, N, matchCondition) == [10, 9, 8, 4, 7])
간단한 Python :
N = 3
data = [1, 10, 2, 9, 3, 8, 4, 7]
def matchCondition(x):
return x < 5
c = 1
l = []
for x in data:
if c > N or not matchCondition(x):
l.append(x)
else:
c += 1
print(l)
원하는 경우 쉽게 발전기로 전환 할 수 있습니다.
def filter_first(n, func, iterable):
c = 1
for x in iterable:
if c > n or not func(x):
yield x
else:
c += 1
print(list(filter_first(N, matchCondition, data)))
목록 이해력 사용 :
n = 3
data = [1, 10, 2, 9, 3, 8, 4, 7]
count = 0
def counter(x):
global count
count += 1
return x
def condition(x):
return x < 5
filtered = [counter(x) for x in data if count < n and condition(x)]
이는 또한 부울 단락으로 인해 n 개의 요소가 발견 된 후에도 조건 확인을 중지합니다 .
시작 Python 3.8
및 할당 표현식 (PEP 572) ( :=
연산자) 의 도입으로 목록 이해 내에서 변수를 사용하고 증가시킬 수 있습니다.
# items = [1, 10, 2, 9, 3, 8, 4, 7]
total = 0
[x for x in items if not (x < 5 and (total := total + 1) <= 3)]
# [10, 9, 8, 4, 7]
이:
- Initializes a variable
total
to0
which will symbolize the number of previously matched occurrences within the list comprehension - Checks for each item if it both:
- matches the exclusion condition (
x < 5
) - and if we've not already discarded more than the number of items we wanted to filter out by:
- incrementing
total
(total := total + 1
) via an assignment expression - and at the same time comparing the new value of
total
to the max number of items to discard (3
)
- incrementing
- matches the exclusion condition (
'program tip' 카테고리의 다른 글
방법과 기능의 차이점은 무엇입니까? (0) | 2020.12.04 |
---|---|
배경색에 따라 CSS 글꼴 색상 반전 (0) | 2020.12.04 |
LINQ 쿼리에서 NameValueCollection에 액세스 할 수 있도록 설정 (0) | 2020.12.04 |
복합 색인은 어떻게 작동합니까? (0) | 2020.12.04 |
HTTP 다중 파트 (POST) 요청의 경계 매개 변수는 무엇입니까? (0) | 2020.12.04 |