2010-05-25 16 views
6

in Python, si potrebbe fare qualcosa di simileestratto/slice/riordina gli elenchi in (emacs) lisp?

i = (0, 3, 2) 
x = [x+1 for x in range(0,5)] 
operator.itemgetter(*i)(x) 

per ottenere (1, 4, 3). In (emacs) Lisp, ho scritto questa funzione chiamata estratto che fa qualcosa di simile,

(defun extract (elems seq) 
    (mapcar (lambda (x) (nth x seq)) elems)) 

(extract '(0 3 2) (number-sequence 1 5)) 

ma mi sento come ci dovrebbe essere qualcosa di costruito nel? Tutto quello che so è first, last, rest, nth, car, cdr ... Qual è la strada da percorrere? ~ Grazie in anticipo ~

risposta

4

Se il problema è la velocità, utilizzare (vettore 1 2 3 4 5) anziché una lista e (aref indice vec) per ottenere l'elemento.

(defun extract (elems seq) 
    (let ((av (vconcat seq))) 
    (mapcar (lambda (x) (aref av x)) elems))) 

Se avete intenzione di estrarre dalla stessa sequenza più volte, naturalmente, ha senso per memorizzare la sequenza in un vettore solo una volta. Gli elenchi Python sono infatti matrici monodimensionali, l'equivalente in LISP sono vettori.

+0

Non lo sapevo. Quindi, per questo problema, devo decidere se il sovraccarico di creazione di un vettore vale il sovraccarico aggiuntivo dell'accesso a tempo costante. – hatmatrix

2

Ho solo fatto uno script semplice in elisp, ma è un linguaggio relativamente piccolo. E extract è una funzione molto inefficiente sugli elenchi concatenati, che è la struttura dati predefinita in emacs lisp. Quindi è improbabile che sia integrato.

La soluzione è la soluzione più semplice. È n^2, ma per renderlo più veloce richiede molto più codice.

Qui di seguito è una congettura a come potrebbe funzionare, ma potrebbe anche essere di base completamente fuori:

  1. sorta elems (n log n)
  2. creare una mappa che mappa gli elementi in ordinati elem alla loro indici nell'originale elem (probabilmente n log n, forse n)
  3. iterate tramite seq e ordinati elem. Mantenere solo gli indici in ordinate elem (probabilmente n, forse n log n, a seconda che si tratti di una mappa hash o una mappa ad albero)
  4. sorta il risultato con i valori della mappatura elem (n log n)
+0

Ottimo - grazie ... – hatmatrix

1

Da My Lisp Experiences and the Development of GNU Emacs:

C'erano persone in quei giorni, nel 1985, che ha avuto macchine di un megabyte, senza memoria virtuale. Volevano essere in grado di usare GNU Emacs. Ciò significava che dovevo mantenere il programma il più piccolo possibile.

Ad esempio, al momento l'unico costrutto di ciclo era "while", che era estremamente semplice. Non c'era modo di uscire dall'affermazione del "tempo", bastava fare un tiro e un lancio o testare una variabile che gestiva il ciclo. Questo dimostra quanto stavo spingendo a mantenere le cose piccole. Non avevamo "caar" e "cadr" e così via; "Spremere tutto il possibile" è stato lo spirito di GNU Emacs, lo spirito di Emacs Lisp, fin dall'inizio.

Ovviamente, le macchine ora sono più grandi e non lo facciamo più in quel modo. Inseriamo 'caar' e 'cadr' e così via, e potremmo inserire un altro costrutto di ciclo uno di questi giorni.

Quindi la mia ipotesi è che se non lo vedi, non è lì.