Feedback su implementazione della funzione che confronta i segni interi in Python
Domanda
Ho fatto una piccola funzione che, data una tupla, paragona se tutti gli elementi in questo tupla è dello stesso segno.
per es., Tuple = [-1, -4, -6, -8]
è buono, mentre [-1, -4, 12, -8]
è male. Io non sono sicuro di aver fatto la più intelligente implementazione, quindi so che questo è il posto giusto per chiedere.
def check_consistent_categories(queryset):
try:
first_item = queryset[0].amount
if first_item < 0:
for item in queryset:
if item > 0:
return False
return True
else:
for item in queryset:
if item < 0:
return False
return True
except:
return False
Soluzione
Questo aiuto potrebbe voi:
def all_same_sign(ints):
return all(x < 0 for x in ints) or all(x > 0 for x in ints)
Si può decidere di cambiare
Altri suggerimenti
Dopo @ soluzione di EOL, ma opere senza lista indicizzazione o l'iterazione più volte.
def all_same_sign(sequence):
items = iter(sequence)
try:
first = items.next() > 0
except StopIteration:
return True
return all((item > 0) == first for item in items)
Questa è verificato anche a me, ma non approfitta di tutte / qualsiasi cortocircuito:
def all_same_sign(sequence):
return len(set(item > 0 for item in sequence)) <= 1
Un solo nit indipendenti, dal momento che si sta facendo questo:
try:
[...]
except:
[...]
Stai ignorando all
delle eccezioni, essere molto attenti mio amico, questo sarà nascosto un sacco di bug, invece sempre essere precisi, mentre facendo la gestione delle eccezioni per esempio:
try:
[...]
except IndexError:
# Handle out of index
except IOError:
# Handle I/O error
ecc. Tenetelo a mente, mentre la codifica di un grande applicazione Python.
Ecco un bel modo divinatorio di fare questo (utilizzando all()
):
from math import copysign
sign = lambda x: copysign(1, x) # Sign function
def check_consistent_categories(sequence):
main_sign = sign(sequence[0])
return all(sign(y) == main_sign for y in sequence)
(per Python 2.6+, che ha introdotto la funzione math.copysign()
). Questa soluzione ritiene che 0 è positivo.
soluzione Mark Byers' è più flessibile, però, ed è anche probabilmente più leggibile.
Perché non approfittare del fatto che, se tutti i numeri sono lo stesso segno, allora la somma del valore assoluto di ogni singolo numero sarà pari al valore assoluto della somma di ogni numero?
def check_sign(queryset):
return abs(sum(queryset)) == sum(map(abs, queryset))
Esempio che mostra i dettagli del Math
Caso 1: Tutti i numeri hanno lo stesso segno
a = (-1, -4, -8)
sum(a) = -13
abs(sum(a)) = 13 # the absolute value of the tuple's sum
map(abs, a) = [1, 4, 8]
sum(map(abs, a)) = 13 # the tuple's sum of each element's absolute value
Entrambi i metodi producono 13, in modo che i segni sono gli stessi.
Caso 2: Non tutti i numeri hanno lo stesso segno
b = (-1, 4, 8)
sum(b) = 11
abs(sum(b)) = 11 # the absolute value of the tuple's sum
map(abs, b) = [1, 4, 8]
sum(map(abs, b)) = 13 # the tuple's sum of each element's absolute value
I metodi producono numeri differenti (11 e 13), in modo che i segni non sono tutti uguali.
Ecco uno che funziona bene con i generatori ecc troppo
def all_same_sign(ints):
ints = iter(ints)
first_is_positive = next(ints) > 0
return all( (x>0) == first_is_positive for x in ints)
Se ints
è vuoto, si ottiene un'eccezione StopIteration.
Questa versione gorups 0 con i numeri negativi. Utilizzare >=
se desiderate gruppo con i numeri positivi anziché
def all_same_sign(iterable):
# Works with any iterable producing any items that can be compared to zero.
# Iterates through the input no more than once, and this fact is immediately
# obvious from the code.
# Exits as soon as a bad combination has been detected.
pos = neg = zero = False
for item in iterable:
if item > 0:
pos = True
elif item < 0:
neg = True
else:
zero = True
# Adjust the following statement if a different
# treatment of zero is required.
# Redundant parentheses added for clarity.
if (pos and neg) or zero:
return False
return True
Se i numeri sono ordinati avete solo bisogno di confrontare le estremità. Se non li si poteva ordinare:
def same_sign(numbers):
numbers = sorted(numbers)
#if numbers[0]==0: return True Uncomment if you consider 0 positive
if numbers[0]*numbers[-1]>0: return True
return False
Se si è modificato questo per >=0
a zero sarebbe considerato segno neutro. Non sono sicuro se questa è un'implementazione migliore rispetto alle risposte attuali, ma potrebbe essere più veloce per grandi insiemi di dati.
Utilizzando il principio che moltiplicando i numeri dà un risultato positivo se tutti lo stesso, altrimenti negativo,
import operator
def all_same_sign(intlist):
return reduce(operator.mul, intlist) > 0
>>> all_same_sign([-1, -4, -6, -8])
True
>>> all_same_sign([-1, -4, 12, -8])
False
Questa non gestisce zeri anche se ...