在(emacs)lisp中提取/切片/重新排序列表?

在(emacs)lisp中提取/切片/重新排序列表?,lisp,elisp,Lisp,Elisp,在python中,您可以执行以下操作 i = (0, 3, 2) x = [x+1 for x in range(0,5)] operator.itemgetter(*i)(x) 获取(1,4,3)。 在(emacs)lisp中,我编写了一个名为extract的函数,它做了类似的事情 (defun extract (elems seq) (mapcar (lambda (x) (nth x seq)) elems)) (extract '(0 3 2) (number-sequence

在python中,您可以执行以下操作

i = (0, 3, 2)
x = [x+1 for x in range(0,5)]
operator.itemgetter(*i)(x)
获取
(1,4,3)
。 在(emacs)lisp中,我编写了一个名为extract的函数,它做了类似的事情

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

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

但我觉得应该有一些内在的东西?我只知道
第一个、最后一个、休息、第n个、汽车、cdr
。。。怎么走?~提前感谢~

我只使用elisp编写了简单的脚本,但它是一种相对较小的语言。而
extract
在链表上是一个非常低效的函数,这是emacs lisp中的默认数据结构。所以它不太可能是内置的

您的解决方案是最简单的。它是n^2,但是要使它更快,需要更多的代码

下面是对其工作原理的猜测,但也可能完全偏离了基准:

  • 排序
    elems
    (n日志n)
  • 创建一个映射,将已排序的
    elem
    中的元素映射到其原始
    elem
    中的索引(可能是n log n,可能是n)
  • 遍历
    seq
    并排序
    elem
    。仅在已排序的
    元素中保留索引(可能是n,可能是n log n,取决于它是哈希映射还是树映射)
  • 根据
    元素的值对结果进行排序
    映射(n log n)
  • 发件人:

    在1985年的那些日子里,有人拥有没有虚拟内存的1兆字节机器。他们希望能够使用GNU Emacs。这意味着我必须让程序尽可能小

    例如,当时唯一的循环构造是“while”,它非常简单。没有办法突破while语句,您只需执行捕获和抛出,或者测试运行循环的变量。这显示了我在努力使事情变得小。我们没有“caar”和“cadr”等等;“挤出一切可能”从一开始就是GNU Emacs的精神,Emacs Lisp的精神

    显然,现在机器更大了,我们不再这样做了。我们加入了“caar”和“cadr”等等,也许有一天我们会加入另一个循环构造


    因此,我的猜测是,如果你看不到它,它就不在那里。

    如果你的问题是速度,那么使用(向量1 2 3 4 5)而不是列表和(aref vec index)来获取元素

    (defun extract (elems seq)
      (let ((av (vconcat seq)))
        (mapcar (lambda (x) (aref av x)) elems)))
    
    如果要多次从同一序列中提取,那么只需将序列存储在向量中一次就有意义了。
    Python列表实际上是一维数组,LISP中的等价物是向量。

    不知道这一点。所以对于这个问题,我必须决定创建向量的开销是否值得常数时间访问的额外开销。