Commentaires sur la mise en œuvre de la fonction qui compare les signes entiers en Python

StackOverflow https://stackoverflow.com/questions/4558326

  •  14-10-2019
  •  | 
  •  

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
Était-ce utile?

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 à <= et> = selon la façon dont vous voulez traiter 0.

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 ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top