2009-06-02 6 views
32

primo luogo, assumere ogni sequenze specifiche strutture avrebbero diversi modi per rimuovere un elemento: Vettori potrebbe essere per indice, Elenco potrebbe essere rimuovere prima o l'ultima, Set dovrebbe essere passando dell'articolo reale da rimuovere , ecc.Come posso rimuovere un elemento da una sequenza in Clojure?

In secondo luogo, presumo che ci siano alcuni metodi per la rimozione che sono indipendenti dalla struttura; funzionano sull'interfaccia seq.

Dal momento che le sequenze sono immutabili in Clojure, sospetto che ciò che stai effettivamente facendo sia una copia economica dell'originale, solo senza l'articolo originale. Ciò significa che la rimozione delle liste potrebbe essere utilizzata, ma sospetto che sarebbe inutilmente prolisso.

Fornire alcuni esempi idiomatici dei diversi modi per rimuovere elementi dalle sequenze Clojure.

risposta

41

Non esiste una singola interfaccia per rimuovere elementi da tutti i tipi di strutture dati Clojure, probabilmente a causa delle diverse caratteristiche delle prestazioni.

(disj #{:foo :bar} :foo)  ; => #{:bar} 
(dissoc {:foo 1 :bar 2} :foo) ; => {:bar 2} 
(pop [:bar :foo])    ; => [:bar] 
(pop (list :foo :bar))   ; => (:bar) 

Questi inoltre lavorare (restituendo un seq):

(remove #{:foo} #{:foo :bar})  ; => (:bar) 
(remove #{:foo} [:foo :bar])  ; => (:bar) 
(remove #{:foo} (list :foo :bar)) ; => (:bar) 

Questo non funziona per hash-mappe, perché quando eseguire iterazioni su una mappa, si ottiene coppie chiave/valore. Ma questo funziona:

(remove (fn [[k v]] (#{:foo} k)) {:foo 1 :bar 2}) ; => ([:bar 2]) 
+0

Grazie Brian, questo è quello che stavo cercando. La tua citazione di subvec non sembra corrispondere alla documentazione: "Restituisce un vettore persistente degli elementi nel vettore dall'inizio (incluso) alla fine (esclusivo). Se non viene fornita la fine, il valore predefinito è (vettore di conteggio)." Intendevi dire che potresti concatenare due chiamate subvec per escludere l'elemento "rimosso"? – rcampbell

+0

Sì, questo è quello che intendevo. Con il senno di poi potrebbe essere troppo maldestro anche solo prendere in considerazione. Lo rimuoverò dal post. –

+0

['subvec'] (http://clojuredocs.org/clojure_core/clojure.core/subvec) è degno di nota (per i vettori), perché funziona in tempo O (1). –

2

Come estensione della risposta di Brian Carper. Dipende da cosa farai con il risultato. Se stai trasmettendo il risultato a qualcosa che vuole lavorare sull'intero insieme di dati (cioè stamparlo) È idiomatico fare un seq e usare il filtro o rimuovere per risolvere il problema pigramente. Se invece si sta modificando la struttura dei dati da salvare per vari usi successivi, la creazione di un seq su di esso perderebbe le sue caratteristiche di aggiornamento favorevoli, quindi in questo caso è meglio usare la funzione di aggiornamento specifica per quella struttura dati.