Domanda

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

(Almeno in ActiveState Python 3.1 implementazione.)

ho capito nan è un oggetto strano, quindi non sarei sorpreso se si presenta in luoghi casuali nel Ordina risultati. Ma ha anche scombina l'ordinamento per i numeri non Nan nel contenitore, che è davvero inaspettato.

ho chiesto a un correlata domanda su max , e sulla base di tale capisco perché sort funziona in questo modo. Ma questo dovrebbe essere considerato un bug?

Documentazione dice solo "Return un nuovo elenco ordinato [...]" senza specificare alcun dettaglio.

EDIT: Io ora sono d'accordo che questo non è in violazione dello standard IEEE. Tuttavia, si tratta di un bug da qualsiasi punto di vista il senso comune, credo. Anche Microsoft, che non è noto per ammettere i propri errori, spesso, ha riconosciuto questo come un bug, e fissato nella sua ultima versione: http://connect.microsoft.com/VisualStudio/feedback/details/363379/bug -in-list-double-sort-in-list-che-contiene-double-nan .

In ogni caso, ho finito dopo @ risposta di Khachik:

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

Ho il sospetto che si traduce in un calo di prestazioni rispetto al linguaggio farlo per impostazione predefinita, ma almeno funziona (salvo eventuali bug che ho introdotto).

È stato utile?

Soluzione

Le risposte precedenti sono utili, ma forse non chiara per quanto riguarda la radice del problema.

In qualsiasi lingua, sorta applica un dato ordine, definito da una funzione di confronto o in qualche altro modo, sul dominio dei valori di ingresso. Ad esempio, minore di, operator <, pseudonimo potrebbe essere utilizzato in tutta se e solo se meno di definisce un ordinamento adeguato sui valori di ingresso.

Ma questo è specificamente non è vero per i valori in virgola mobile e di meno-che: "Nan è ordinata: non è uguale a, maggiore di, o meno di ogni altra cosa, compreso se stesso." ( Cancella prosa da manuale GNU C, , ma si applica a tutti IEEE754 moderna basata virgola mobile )

Quindi, le soluzioni possibili sono:

  
      
  1. rimuovere le NaNs prima, rendendo il dominio di ingresso ben definito tramite <   (O altra funzione di ordinamento utilizzato)
  2.   
  3. definire una funzione di confronto personalizzato (anche noto come predicato) che fa   definire un ordinamento per NaN, come meno di qualsiasi numero o maggiore   rispetto a qualsiasi numero.
  4.   

In entrambi approccio può essere utilizzato, in qualsiasi lingua.

In pratica, considerando pitone, preferirei per rimuovere le NaNs se uno non si cura molto di prestazioni più veloci o se la rimozione di NaNs è un comportamento desiderato nel contesto.

In caso contrario, è possibile utilizzare una funzione predicato idoneo tramite "cmp" nelle versioni più vecchie di Python, o tramite esso e functools.cmp_to_key(). Quest'ultimo è un po 'più scomodo, naturalmente, che rimuovere i NaN prima. E attenzione sarà richiesto per evitare peggio prestazioni, al momento di definire questa funzione predicato.

Altri suggerimenti

Il problema è che non c'è nessun ordine corretto se l'elenco contiene un NAN, dal momento che una sequenza a1, a2, a3, ..., an è ordinato se a1 <= a2 <= a3 <= ... <= un . Se uno di questi valori è un un NAN poi le pause di proprietà ordinati, dal momento che per ogni a, un <= NAN NAN e <= a sono entrambi falsi.

Io non sono sicuro circa il bug, ma la soluzione potrebbe essere il seguente:

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

che si traduce in:

('nan', 1, 2)

o rimuovere nans prima cernita o qualsiasi altra cosa.

IEEE754 è lo standard che definisce operazioni in virgola mobile in questo caso. Questo standard definisce l'operazione di confrontare operandi, almeno uno dei quali è un NaN, come un errore. Quindi, questo non è un bug. È necessario affrontare le NaNs prima di operare sul vostro allineamento.

Supponendo che si desidera conservare i NaNs e l'ordine loro come i "valori" più bassi, ecco un workaround lavorare sia con non univoco nan , NumPy unica nan , numerico e non numerico oggetti:

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']
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top