목록의 모든 요소가 조건과 일치하는지 확인하는 방법은 무엇입니까?


208

20000 목록으로 구성된 목록이 있습니다. 각 목록의 세 번째 요소를 플래그로 사용합니다. 적어도 하나의 요소 플래그가 0 인 한이 목록에서 일부 작업을 수행하고 싶습니다.

my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]

처음에는 모든 플래그가 0입니다. while 루프를 사용하여 하나 이상의 요소 플래그가 0인지 확인합니다.

def check(list_):
    for item in list_:
        if item[2] == 0:
            return True
    return False

check(my_list)반환 하면 True목록에서 계속 작업합니다.

while check(my_list):
    for item in my_list:
        if condition:
            item[2] = 1
        else:
            do_sth()

사실, my_list에서 반복 할 때 요소를 제거하고 싶었지만 반복 할 때 항목을 제거 할 수 없습니다.

원래 my_list에는 플래그가 없었습니다.

my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]

반복하면서 요소를 제거 할 수 없으므로이 플래그를 발명했습니다. 그러나이 my_list항목에는 많은 항목 이 포함되어 있으며 while루프는 각 for루프 에서 모든 항목을 읽고 많은 시간을 소비합니다! 의견 있으십니까?


3
데이터 구조가 문제에 적합하지 않은 것 같습니다. 문맥을 조금 더 설명하면 더 적절한 것을 제안 할 수 있습니다.
uselpa

항목 을 제거하는 대신 None또는 []목록을 반복 하면서 항목을 바꿀 수 있습니다. 내부 루프의 각 패스 전에 모든 항목을 반복하는 'check ()`로 전체 목록을 확인하는 것은 매우 느린 접근 방식입니다.
martineau

답변:


402

여기서 가장 좋은 대답은 all()이 상황에 내장 된를 사용 하는 것입니다. 이를 생성기 표현식 과 결합하여 원하는 결과를 깨끗하고 효율적으로 생성합니다. 예를 들면 다음과 같습니다.

>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False

참고 all(flag == 0 for (_, _, flag) in items)로 직접 동등은 all(item[2] == 0 for item in items),이 경우 읽을 조금 좋네요.

필터 예제의 경우 목록 이해 (물론 적절한 경우 생성기 표현식을 사용할 수 있음) :

>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]

적어도 하나의 요소가 0인지 확인하려면 any()더 읽기 쉬운 옵션을 사용 하는 것이 좋습니다 .

>>> any(flag == 0 for (_, _, flag) in items)
True

람다 사용에 대한 나의 잘못, 파이썬의 모든 것은 Haskell 등의 첫 번째 인수로 함수를 받아들이지 않습니다. al., 나는 대답을 목록 이해력으로 변경했습니다. :)
Hampus Nilsson

3
@HampusNilsson 목록 이해는 생성기 식과 다릅니다. 마찬가지로 all()any()단락, 예를 들어, 광산의 첫번째 값이 평가되면 False, all()실패 및 복귀 더 값을 체크하지 False. 예제는 전체 비교 목록을 먼저 생성한다는 점을 제외하고는 동일하게 수행되므로 아무것도 처리하지 않아도됩니다.
Gareth Latty

14

목록의 항목이 조건을 위반하는지 확인하려면 all다음을 사용하십시오 .

if all([x[2] == 0 for x in lista]):
    # Will run if all elements in the list has x[2] = 0 (use not to invert if necessary)

일치하지 않는 모든 요소를 ​​제거하려면 filter

# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2] != 0, listb)

2
당신은 제거 할 수 있습니다 [...]all(...)그 다음 대신뿐만 아니라 당신에게 두 개의 문자를 저장하는 목록의 발전기를 만들 수 있기 때문에뿐만 아니라 메모리와 시간을 절약 할 수 있습니다. 생성기를 사용하면 한 번에 하나의 항목 만 계산되고 (더 이상 사용되지 않으므로 이전 결과가 삭제됨) 항목 중 하나가 나오면 False나머지는 계산을 중지합니다.
InQβ

7

itertools의 이와 같은 것을 사용할 수 있습니다. 조건이 충족되면 명령문이 실패합니다. 반대 방법은 떨어질 것입니다

for x in itertools.takewhile(lambda x: x[2] == 0, list)
    print x

0

사용하는 또 다른 방법 itertools.ifilter. 이것은 진실성과 프로세스를 검사합니다 (을 사용하여 lambda)

견본-

for x in itertools.ifilter(lambda x: x[2] == 0, my_list):
    print x

0

이 방법은 다음을 사용하는 것보다 약간 더 유연합니다 all().

my_list = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
all_zeros = False if False in [x[2] == 0 for x in my_list] else True
any_zeros = True if True in [x[2] == 0 for x in my_list] else False

간결하게 :

all_zeros = not False in [x[2] == 0 for x in my_list]
any_zeros = 0 in [x[2] for x in my_list]

당신은 단순히 all_zeros = False in [x[2] == 0 for x in my_list]또는 심지어 0 in [x[2] for x in my_list]그에 대응하여 말할 수 없었 any_zeros습니까? 에 비해 크게 개선 된 점은 없습니다 all().
tripleee

아니오, 귀하의 버전은으로 all_zeros = False in [x[2] == 0 for x in my_list]평가되는 False반면 내 버전 은으로 평가됩니다 True. 당신이 그것을 바꾸면 그것은 all_zeros = not (False in [x[2] == 0 for x in my_list])내 것과 같습니다. 그리고 0 in [x[2] for x in my_list]분명히 일할 것입니다 any_zeros. 그러나 나는 당신의 생각의 간결함을 좋아합니다. 그래서 나는 대답을 업데이트 할 것입니다
mulllhausen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.