Question

retourne sorted([2, float('nan'), 1]) [2, nan, 1]

(au moins sur la mise en œuvre ActiveState Python 3.1.)

Je comprends nan est un objet bizarre, donc je ne serais pas surpris si elle apparaît dans des endroits aléatoires dans le résultat de tri. Mais elle a aussi bousille le tri pour les numéros non-nan dans le récipient, ce qui est vraiment inattendu.

J'ai posé une question connexe sur max , et sur la base que je comprends pourquoi fonctionne sort comme ça. Mais si cela est considéré comme un bug?

Documentation dit simplement "Retour une nouvelle liste triée [...]", sans préciser les détails.

EDIT: Je suis d'accord maintenant que ce n'est pas en violation de la norme IEEE. Cependant, il est un bug de tout point de vue de bon sens, je pense. Même Microsoft, qui n'est pas connu d'admettre leurs erreurs souvent, a reconnu celui-ci comme un bug, et fixe dans la dernière version: http://connect.microsoft.com/VisualStudio/feedback/details/363379/bug -en-liste-double tri dans la liste, qui contient double-nan .

Quoi qu'il en soit, je me suis retrouvé à la suite @ réponse de Khachik:

sorted(list_, key = lambda x : float('-inf') if math.isnan(x) else x)

Je soupçonne que cela se traduit par une baisse de performance par rapport à la langue par défaut le faire, mais au moins cela fonctionne (sauf les bugs que j'ai présenté).

Était-ce utile?

La solution

Les réponses précédentes sont utiles, mais peut-être pas clair quant à la racine du problème.

Dans toutes les langues, applique un ordre donné sorte, défini par une fonction de comparaison ou d'une autre manière, sur le domaine des valeurs d'entrée. Par exemple, moins que, operator <, pourrait être utilisé a.k.a. tout au long si et seulement si moins définit un ordre approprié sur les valeurs d'entrée.

Mais ce n'est pas spécifiquement vrai pour les valeurs à virgule flottante et moins que: « NaN est non ordonnée: il n'est pas égal, supérieur ou inférieur à quoi que ce soit, y compris lui-même. » ( prose claire de manuel GNU C, mais applique à tous IEEE754 moderne basé virgule flottante )

Ainsi, les solutions possibles sont:

  
      
  1. NaN supprimer les premier, ce qui rend le domaine d'entrée bien définie via <   (Ou autre fonction de tri utilisé)
  2.   
  3. définir une fonction de comparaison personnalisée (prédicat a.k.a.) qui ne   définir un ordre de NaN, par exemple inférieure à un nombre quelconque, ou plus   que tout nombre.
  4.   

approche peut être utilisée soit, dans toutes les langues.

En pratique, compte tenu de python, je préfère retirer les NaN si vous soit ne se soucient pas beaucoup sur les performances ou la plus rapide si la suppression NaN est un comportement souhaité dans le contexte.

Sinon, vous pouvez utiliser une fonction sous-jacente appropriée via « cmp » dans les versions de python plus, ou via ce et functools.cmp_to_key(). Ce dernier est un peu plus gênant, naturellement, que la suppression des NaN premier. Et les soins seront nécessaires pour éviter pire performances, lors de la définition de cette fonction sous-jacente.

Autres conseils

Le problème est qu'il n'y a pas d'ordre correct si la liste contient une NAN, étant donné qu'une séquence a1, a2, a3, ..., an est triée si a1

Je ne suis pas sûr du bug, mais la solution de contournement peut être le suivant:

sorted(
    (2, 1, float('nan')),
    lambda x,y: x is float('nan') and -1 
                or (y is float('nan') and 1
                or cmp(x,y)))

qui se traduit par:

('nan', 1, 2)

ou supprimer nans avant le tri ou quoi que ce soit d'autre.

IEEE754 est la norme définissant les opérations en virgule flottante dans ce cas. Cette norme définit les opérations de comparaison d'opérandes, au moins l'un qui est un NaN, comme une erreur. Par conséquent, ce n'est pas un bug. Vous devez traiter les NaN avant de faire fonctionner sur votre tableau.

En supposant que vous voulez garder les NaN et les commander comme le plus "valeurs", voici une solution de travail à la fois avec nan non unique , numpy uniques nan , numérique et non numérique objets:

def is_nan(x):
    return (x is np.nan or x != x)

list_ = [2, float('nan'), 'z', 1, 'a', np.nan, 4, float('nan')]
sorted(list_, key = lambda x : float('-inf') if is_nan(x) else x)
# [nan, nan, nan, 1, 2, 4, 'a', 'z']
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top