如何映射矢量并获取矢量?


15

我发现唯一可行的方法是

(eval `(vector ,@(mapcar #'1+ [1 2 3 4])))
=> [2 3 4 5]

但似乎太复杂,是“正确”的方式。

Answers:


19

使用cl-map,而不是:

(cl-map 'vector #'1+ [1 2 3 4])

一些额外的背景知识:cl-mapCommon Lisp map函数,可以概括为序列类型:

(cl-map 'vector #'1+ '[1 2 3 4]) ;; ==> [2 3 4 5]
(cl-map 'list   #'1+ '(1 2 3 4)) ;; ==> (2 3 4 5)
(cl-map 'string #'upcase "abc")  ;; ==> "ABC"

它还可以在序列类型之间进行转换(例如,这里的输入是列表,而输出是向量):

(cl-map 'vector #'1+ '(1 2 3 4)) ;; ==> [2 3 4 5]

1
18秒钟“胜利者” :)但是,cl库没有发出编译器警告吗?(主要是因为FSF令人讨厌吗?)
肖恩·阿雷德

1
FWIW,我认为字节编译问题与旧cl库有关,而不是与重新编译的cl-lib库有关。例如,我没有(defun fnx () (cl-map 'vector #'1+ '[1 2 3 4])),然后再得到任何警告(byte-compile 'fnx)
Dan

2
即使您使用兼容性cl-lib,我认为您也会在较旧的emacs(24.2)上收到警告。不过,我不必担心,您必须选择战斗。
马拉巴巴2014年

16

由于我被击败了18秒,因此这是没有cl库的一种更简单,更安全的方法。它还不评估元素。

(apply #'vector (mapcar #'1+ [1 2 3 4])) ;; => [2 3 4 5]

那也很好!回复:您之前对较旧的Emacs的评论:如果您必须预期旧用户,这似乎特别有用。如果只需要在几个地方使用它,这似乎是最有用的,这时您可以权衡轻微的不便与避免cl-lib依赖。

1
很漂亮!我没有考虑过使用apply
肖恩·艾瑞德

我认为(apply #'vector ...)速度可能会稍微快一些,但是为了完整起见,也可以将其替换(vconcat ...)
罗勒

1

对于后来不再需要原始向量并且内存分配对时间很紧迫的情况(例如向量很大)的​​情况,这不是那么优雅的就地变量。

(setq x [1 2 3 4])

(cl-loop for var across-ref x do
         (setf var (1+ var)))

结果存储在中x。如果x最终需要返回表格,可以添加finally return x以下内容:

(cl-loop for var across-ref x do
         (setf var (1+ var))
         finally return x)

1

为了完整起见,请使用seq

(require 'seq)
(seq-into (seq-map #'1+ [1 2 3 4]) 'vector)

Fólkvangr2018-11-12删除的答案完全相同seq-into。用户由于以下原因删除了答案:“我的解决方案不太重要,因为seq库使用了底层的Common Lisp扩展。–Fólkvangr,5月16日,8:53”
Tobias,

@Tobias我想我不同意这种逻辑。无论如何,一切最终都将使用vconcat或vector来结束,但是不同的接口范例对于记录很有用。
肖恩·艾瑞德

没问题。我刚刚看到Fólkvangr(几乎)已删除的答案与您的答案相匹配,并想通知您。无论出于何种原因,看到删除的答案都需要10000 rep :
。– Tobias

@Tobias是的,我从未真正理解为什么这些特权是特定于站点的:-)
Sean Allred

0

您可以使用循环

(let ((v (vector 1 2 3 4)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  v)
;; => [2 3 4 5]

有时您不想修改原始向量,可以复制

(let* ((v0 (vector 1 2 3 4))
       (v (copy-sequence v0)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])

或从头开始创建新载体

(let* ((v0 (vector 1 2 3 4))
       (v (make-vector (length v0) nil)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v0 i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.