Extract / slice / reorder lists in (emacs) lisp?

In python you can do something like

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

to get (1, 4, 3) . In (emacs) lisp, I wrote this function called extract, which does something like this,

 (defun extract (elems seq) (mapcar (lambda (x) (nth x seq)) elems)) (extract '(0 3 2) (number-sequence 1 5)) 

but do I feel there must be something built in? All I know is first, last, rest, nth, car, cdr ... What should I do? ~ Thanks in advance ~

+6
lisp elisp
source share
3 answers

If your problem is speed, use (vector 1 2 3 4 5) instead of list and (isf vec index) to get the item.

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

If you are going to extract from the same sequence many times, of course, it makes sense to save the sequence in the vector only once. Python lists are truly one-dimensional arrays, the equivalent in LISP are vectors.

+4
source share

I did simple scripts in elisp, but it is a relatively small language. And extract is a very inefficient function in linked lists, which is the default data structure in emacs lisp. So it is unlikely that it will be embedded.

Your decision is the simplest. This is n ^ 2, but much more code is required to speed it up.

The following is a hint about how it can work, but it can also be completely disabled:

  • sort elems (n log n)
  • create a map that matches elements in the sorted elem with their indices in the original elem (possibly n log n, possibly n)
  • iterate through seq and sorted elem . Only store indexes in sorted elem (maybe n, maybe n log n, depending on whether it is a hash map or a tree map)
  • sort the result by the values ​​of the mapping elem (n log n)
+2
source share

From My Lisp Experience and Development of GNU Emacs :

In those days, in 1985, there were people who had one megabyte machine without virtual memory. They wanted to be able to use GNU Emacs. This meant that I had to keep the program as small as possible.

For example, at a time when the only loop construct was β€œwhile,” which was extremely simple. There was no way to break out of the while statement, you just had to do the trick and throw, or check the variable that started the loop. This shows how far I have come to keep things small. We did not have "caar" and "cadr" and so on; "squeeze everything possible" is the spirit of GNU Emacs, the spirit of Emacs Lisp, from the very beginning.

Obviously, there are more cars now, and we are no longer doing this. We put "caar" and "cadr", etc., And the other day we could add another loop construction.

So I assume that if you do not see this, it is not.

+1
source share

All Articles