Sprawdź, czy wszystkie wartości na liście są większe niż określona liczba

86
my_list1 = [30,34,56]
my_list2 = [29,500,43]

Jak sprawdzić, czy wszystkie wartości na liście są> = 30? my_list1powinien działać, a my_list2nie powinien.

Jedyne, o czym przyszło mi do głowy, to:

boolean = 0
def func(ls):
    for k in ls:
        if k >= 30:
            boolean = boolean + 1
        else:
            boolean = 0
    if boolean > 0:
        print 'Continue'
    elif boolean = 0:
        pass

Aktualizacja 2016:

Z perspektywy czasu, po poradzeniu sobie z większymi zbiorami danych, w których prędkość naprawdę ma znaczenie i wykorzystaniu numpy... zrobiłbym to:

>>> my_list1 = [30,34,56]
>>> my_list2 = [29,500,43]

>>> import numpy as np
>>> A_1 = np.array(my_list1)
>>> A_2 = np.array(my_list2)

>>> A_1 >= 30
array([ True,  True,  True], dtype=bool)
>>> A_2 >= 30
array([False,  True,  True], dtype=bool)

>>> ((A_1 >= 30).sum() == A_1.size).astype(np.int)
1
>>> ((A_2 >= 30).sum() == A_2.size).astype(np.int)
0

Możesz też zrobić coś takiego:

len([*filter(lambda x: x >= 30, my_list1)]) > 0
O.rka
źródło
Ogólne kwestie, o których należy pamiętać: 1) przypisana booleanzmienna jest lokalna dla funkcji (ponieważ nie ma odpowiedniej globaladnotacji ), oraz 2) boolean = 0jest przypisaniem , a nie porównaniem.
user2864740
Zauważ, że twoja my_list1ma jedną wartość, która nie jest większa niż 30. Zamiast tego jest równa 30. Czy zamiast tego powinno być 31, czy też testujesz tutaj dla większej lub równej 30?
Martijn Pieters

Odpowiedzi:

147

Użyj all()funkcji z wyrażeniem generatora:

>>> my_list1 = [30, 34, 56]
>>> my_list2 = [29, 500, 43]
>>> all(i >= 30 for i in my_list1)
True
>>> all(i >= 30 for i in my_list2)
False

Zauważ, że te testy dla większej lub równej 30, w przeciwnym razie my_list1również nie przejdą testu.

Gdybyś chciał to zrobić w funkcji, użyłbyś:

def all_30_or_up(ls):
    for i in ls:
        if i < 30:
            return False
    return True

np jak najszybciej znaleźć wartość, która udowadnia, że istnieje wartość poniżej 30, powrót i zwrot , jeśli nie znaleziono dowodów przeciwnych.FalseTrue

Podobnie możesz użyć any()funkcji do sprawdzenia, czy co najmniej 1 wartość pasuje do warunku.

Martijn Pieters
źródło
Jaka jest zaleta używania all_30_or_upnad all? Czy nie należy allrównież zaprzestać używania iteratora, gdy tylko zostanie znaleziony negatyw? Byłoby całkiem głupie, prawda?
Hyperboreus
1
@Hyperboreus: oba kończą się, gdy tylko zostanie znaleziony negatyw. Chciałem dać OP inny sposób patrzenia na problem, dając im funkcję zastępującą tę, którą pisali.
Martijn Pieters
@MartijnPieters, Mucho <3
zelusp
9

... jest jakiś powód, dla którego nie możesz użyć min()?

def above(my_list, minimum):
    if min(my_list) >= minimum:
        print "All values are equal or above", minimum
    else:
        print "Not all values are equal or above", minimum

Nie wiem, czy dokładnie tego chcesz, ale technicznie rzecz biorąc, o to prosiłeś ...

Roberto
źródło
2
Wadą tego rozwiązania jest konieczność dotknięcia każdej pozycji listy.
Hyperboreus
2
Zrobiłem małe profilowanie na ten temat. allzwarcia, więc jest znacznie szybciej, jeśli lista się nie kwalifikuje. Ale jeśli lista zawiera wszystkie 30+, minmoże być szybsza. Testowałem z dwoma 1000-elementowymi listami losowych liczb całkowitych, jedną wypełnioną random.randint(0, 100)(niepowodzenie) i jedną wypełnioną random.randint(30, 100). Używanie minzajęło nieco mniej niż połowę czasu na liście 30-100. Ale allzajęło to około 2% czasu minna liście 0-100, więc prawdopodobnie wygrywa, chyba że niepowodzenia na listach są bardzo rzadkie.
Peter DeGlopper
1
Jak się okazało, pierwszy element mojej listy 0-100 był poniżej 30, więc mój test był trochę zdegenerowany. Wymuszenie pierwszego elementu pod-30 na połowie listy minwychodzi nieco szybciej - 0,25 s dla 10000 powtórzeń zamiast 0,32 s dla all. To, co jest szybsze, zależy od charakteru danych, jak można się spodziewać.
Peter DeGlopper
4

Jest wbudowana funkcja all:

all (x > limit for x in my_list)

Bycie ograniczonym wartością większą niż musi mieć wszystkie liczby.

Hyperboreus
źródło
Jak my_list1powinien test True, test prawie na pewno powinien być >= 30, nie > 30.
Martijn Pieters
1
Cóż, kiedy tekst pytania OP zaprzecza samemu sobie, kim jestem, aby ocenić, który jest prawidłowy limit.
Hyperboreus
3

Możesz użyć all():

my_list1 = [30,34,56]
my_list2 = [29,500,43]
if all(i >= 30 for i in my_list1):
    print 'yes'
if all(i >= 30 for i in my_list2):
    print 'no'

Zwróć uwagę, że obejmuje to wszystkie liczby równe 30 lub wyższe, a nie ściśle powyżej 30.

Simeon Visser
źródło
Jak my_list1powinien test True, test prawie na pewno powinien być >= 30, nie > 30.
Martijn Pieters
@MartijnPieters dzięki, teraz zaktualizowane. Pytanie dotyczy powyżej 30, ale >= 30wydaje się zamierzone.
Simeon Visser
Wiem, dlatego wyraziłem to wyraźnie. :-)
Martijn Pieters
2

Ogólny zwycięzca między użyciem np.sum, np.min, a wszystkim wydaje się być np.min pod względem szybkości dla dużych tablic:

N = 1000000
def func_sum(x):
    my_list = np.random.randn(N)
    return np.sum(my_list < x )==0

def func_min(x):
    my_list = np.random.randn(N)
    return np.min(my_list) >= x

def func_all(x):
    my_list = np.random.randn(N)
    return all(i >= x for i in my_list)

(Muszę umieścić definicję np.array wewnątrz funkcji, w przeciwnym razie funkcja np.min zapamiętuje wartość i nie wykonuje ponownie obliczeń podczas testowania prędkości z timeit)

Wydajność "all" zależy w dużej mierze od tego kiedy zostanie znaleziony pierwszy element nie spełniający kryteriów, np.sum musi wykonać trochę operacji, np.min jest najlżejszy pod względem obliczeń w ogólnym przypadku .

Gdy kryteria są prawie natychmiast spełnione i pętla all szybko się kończy, funkcja all wygrywa nieco powyżej np.min:

>>> %timeit func_sum(10)
10 loops, best of 3: 36.1 ms per loop

>>> %timeit func_min(10)
10 loops, best of 3: 35.1 ms per loop

>>> %timeit func_all(10)
10 loops, best of 3: 35 ms per loop

Ale gdy "wszystko" musi przejść przez wszystkie punkty, jest zdecydowanie gorzej i np.min wygrywa:

>>> %timeit func_sum(-10)
10 loops, best of 3: 36.2 ms per loop

>>> %timeit func_min(-10)
10 loops, best of 3: 35.2 ms per loop

>>> %timeit func_all(-10)
10 loops, best of 3: 230 ms per loop

Ale używając

np.sum(my_list<x)

może być bardzo przydatne, gdy chce się wiedzieć, ile wartości znajduje się poniżej x.

Chachni
źródło
0

Możesz wykonać następujące czynności:

def Lists():

    my_list1 = [30,34,56]
    my_list2 = [29,500,43]

    for element in my_list1:
        print(element >= 30)

    for element in my_list2:
        print(element >= 30)

Lists()

Spowoduje to zwrócenie wartości, które są większe niż 30 jako True, a wartości mniejsze jako false.

Filip Grebowski
źródło
0

Piszę tę funkcję

def larger(x, than=0):
    if not x or min(x) > than:
        return True
    return False

Następnie

print larger([5, 6, 7], than=5)  # False
print larger([6, 7, 8], than=5)  # True
print larger([], than=5)  # True
print larger([6, 7, 8, None], than=5)  # False


Pusta lista w min () spowoduje zgłoszenie błędu ValueError. Więc dodałem if not xw stanie.

Wstyd
źródło