Perché i set Python e i dizionari non sono ordinati per impostazione predefinita?

1

Comprendo la differenza tra insiemi ordinati e non ordinati e capisco perché per molti scopi non abbiamo bisogno di serie ordinate. Ma tutte le operazioni impostate sono ancora possibili sui set ordinati, e gli insiemi devono essere memorizzati internamente con qualche ordine in ogni caso, quindi perché i set non sono ordinati di default? L'impatto sul rendimento di preservare l'ordine dei set è troppo grande?

    
posta oulenz 17.11.2017 - 10:57
fonte

5 risposte

4

Il punto non è che il sovraccarico sia particolarmente grande, più che ci sia affatto .

Le funzionalità linguistiche devono sempre trovare un equilibrio tra costo-efficacia. I dizionari sono assolutamente fondamentali per la programmazione Python, quindi sarebbe pessimo per loro essere anche leggermente più lenti di quello che devono essere solo per preservare l'ordine di inserimento, quando la maggior parte delle volte non è necessario ordinare. Era la decisione corretta di scartare l'ordine di inserzione in cambio di un accesso leggermente più veloce e di lasciare la struttura dei dati che preserva l'ordine per classi speciali. Se esistesse un'altra struttura dati che potesse fare tutto ciò che un dettato può fare, e sarebbe stata una ruga meno utilizzata della lingua, le cose potrebbero apparire diverse.

    
risposta data 17.11.2017 - 11:02
fonte
7

È corretto che gli articoli siano archiviati internamente con un certo ordine, ma questo ordine interno è determinato dal codice hash della chiave, che è ciò che consente al recupero di essere così veloce. Quindi, se un set / dict deve essere ordinato, è necessario mantenere una struttura di dati interna separata (ad esempio un elenco ordinato di chiavi) per questo.

Questo ovviamente aumenterebbe le dimensioni. Ma forse peggio, influenzerà le prestazioni. Ad esempio, la rimozione di un elemento da un set è un'operazione O (1), ma se deve anche rimuovere la chiave da un elenco ordinato interno diventa O (n). Tale costo sarebbe disastroso per alcune applicazioni. Dato che è piuttosto raro che tu abbia bisogno di un set ordinato, tale compromesso non vale la pena per i tipi di set / dict standard.

    
risposta data 17.11.2017 - 11:12
fonte
3

Un insieme ordinato è possibile solo quando gli elementi da memorizzare hanno un ordinamento (cioè un metodo di confronto) in primo luogo - ma non sempre è un dato.

L'implementazione set / mappa predefinita nella maggior parte degli ambienti al giorno d'oggi si basa su un hashtable autoresizing, che presenta questi vantaggi:

  • veloce
  • utilizza meno memoria
  • non richiede che gli elementi forniscano un ordinamento

sets have to be stored internally with some order anyway

Ma questo ordine interno non ha necessariamente alcun significato, né rimane lo stesso. Infatti, una proprietà di hashtables che a volte confonde sviluppatori inesperti è che l'ordine di iterazione, che è basato sull'ordinamento interno, può cambiare completamente quando gli elementi vengono aggiunti (cioè quando viene attivato un ridimensionamento) o tra diversi viene eseguito.

    
risposta data 17.11.2017 - 11:09
fonte
2

La tua premessa non è corretta. A partire da Python 3.6, dict s ricorda il loro ordine di inserimento . Questo è attualmente un dettaglio di implementazione, ma sarà probabilmente promosso a una funzionalità linguistica completa nel prossimo futuro. Nel frattempo, per il caso specifico di **kwargs , la conservazione dell'ordine è specificatamente garantita.

    
risposta data 17.11.2017 - 23:06
fonte
1

L'idea generale alla base di un set o di un dizionario è che si prevede di eseguire molte operazioni di ricerca. È ottimizzato per le suddette operazioni di ricerca utilizzando un hash che consente la ricerca O (1) nella maggior parte dei casi.

L'ordine viene eseguito utilizzando matrici o elenchi concatenati e, in effetti, eseguendo operazioni in cui l'ordine è importante, sono ottimizzati per che come l'aggiunta di un valore alla fine o all'inizio.

Per la natura di queste due strutture dati, nessuno dei due è ottimizzato per entrambi. Questo non vuol dire che non sia possibile, ma coinvolge entrambe le strutture dati se si desidera ottimizzare sia la ricerca che le operazioni basate sugli ordini.

Quindi hai questo compromesso tra:

ottimizzazione dell'operazione di ricerca < = > operazioni basate sugli ordini < = > utilizzo della memoria

Il consenso generale è che come programmatore, in generale, si desidera ottimizzare l'uno o l'altro, ma non entrambi, e certamente nessuno si difende raddoppiando l'utilizzo della memoria quando è solo necessario ottimizzare uno dei due.

Detto questo, ci sono sono implementazioni con entrambi, o almeno in Java, in particolare LinkedHashMap è sia un array che un dizionario basato su hash. A volte potresti aver bisogno di entrambi, ma è consigliabile utilizzare ArrayList se hai bisogno solo di un elenco e di un HashMap se hai solo bisogno di un dizionario.

    
risposta data 17.11.2017 - 13:51
fonte

Leggi altre domande sui tag