Commentaires sur la mise en œuvre de la fonction qui compare les signes entiers en Python
Question
Je l'ai fait une petite fonction qui, étant donné un tuple, compare si tous les éléments de ce tuple est du même signe.
par exemple., Tuple = [-1, -4, -6, -8]
est bon, alors que [-1, -4, 12, -8]
est mauvais. Je ne suis pas sûr que je l'ai fait la plus intelligente mise en œuvre, donc je sais que c'est le lieu de demander.
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
La solution
Cela pourrait vous aider:
def all_same_sign(ints):
return all(x < 0 for x in ints) or all(x > 0 for x in ints)
Vous voudrez peut-être changer
Autres conseils
Après @ la solution de EOL, mais fonctionne sans indexation de liste ou itérer plusieurs fois.
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)
Ceci est également venu à moi, mais ne profite pas de tous / tout court-circuit:
def all_same_sign(sequence):
return len(set(item > 0 for item in sequence)) <= 1
Juste un nit sans rapport, puisque vous faites ceci:
try:
[...]
except:
[...]
Vous ignorez all
des exceptions, soyez très prudent mon ami, cela se cacher beaucoup de bugs, au lieu toujours être précis tout en faisant la gestion des exceptions par exemple:
try:
[...]
except IndexError:
# Handle out of index
except IOError:
# Handle I/O error
etc. Gardez cela à l'esprit tout le codage d'une application Python plus grand.
Voici une façon agréable pythonique de le faire (en utilisant 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)
(pour Python 2.6+, qui a introduit la fonction math.copysign()
). Cette solution estime que 0 est positif.
La solution de Mark Byers est plus souple, cependant, et il est également sans doute plus lisible.
Pourquoi ne pas tirer profit du fait que si tous les chiffres sont le même signe, la somme de la valeur absolue de chaque numéro sera égal à la valeur absolue de la somme de chaque numéro?
def check_sign(queryset):
return abs(sum(queryset)) == sum(map(abs, queryset))
Exemple Affichage Détails de la Math
Cas 1: Tous les chiffres ont le même signe
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
Les deux méthodes donnent 13, de sorte que les signes sont les mêmes.
Cas n ° 2: Tous les chiffres ont le même signe
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
Les méthodes donnent des nombres différents (11 et 13), de sorte que les signes ne sont pas tous les mêmes.
En voici un qui fonctionne très bien avec des générateurs, etc. trop
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)
Si ints
est vide, vous obtenez une exception StopIteration.
Cette version gorups 0 avec les numéros négatifs. Utilisez >=
si vous souhaitez groupe avec les chiffres positifs au lieu
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
Si vos chiffres sont triés vous suffit de comparer les extrémités. Sinon, vous pouvez les trier:
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
Si vous avez changé cela >=0
zéro serait considéré comme signe neutre. Je ne sais pas si cela est une meilleure mise en œuvre que les réponses actuelles, mais il pourrait être plus rapide pour les grands ensembles de données.
En utilisant le principe que la multiplication de vos chiffres donne un résultat positif si tous les mêmes, négatif autre,
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
Cela ne traite pas des zéros si ...