【问题标题】:Merging two vectors with fill-pointer in the resulting vector在结果向量中使用填充指针合并两个向量
【发布时间】:2019-07-17 15:34:12
【问题描述】:

我有两个带有填充指针的向量。我需要merge 这些向量,因此有一个新的向量,它仍然有一个填充指针。

(defparameter *a* (make-array 3 :fill-pointer 3
                                :initial-contents '(1 3 5)))
(defparameter *b* (make-array 3 :fill-pointer 3
                                :initial-contents '(0 2 4)))
(type-of *a*)
;;=> (VECTOR T 6)

;; Pushing new elements works as intended.
(vector-push-extend 7 *a*)
(vector-push-extend 6 *b*)
;; Now we create a new vector by merging *a* and *b*.
(defparameter *c* (merge 'vector *a* *b* #'<))
;;=> #(0 1 2 3 4 5 6 7)
(type-of *c*)
;;=> (SIMPLE-VECTOR 8)

;; The type of this new vector does not allow pushing elements.
(vector-push-extend 8 *c*)

;; The value
;;   #(0 1 2 3 4 5 6 7)
;; is not of type
;;   (AND VECTOR (NOT SIMPLE-ARRAY))
;;    [Condition of type TYPE-ERROR]

我似乎找不到要指定给merge 的类型,因此结果将具有填充指针。我想明显的解决方法是:

  • 自己编写一个merge 函数,声明一个新向量并以正确的顺序执行插入。
  • 使用填充指针将结果复制到另一个向量中。

当然,如果有办法使用标准中的merge 来做到这一点,那么这两种解决方法都非常不令人满意。

【问题讨论】:

  • (defparameter *d* (make-array (length *c*) :fill-pointer (length *c*) :initial-contents *c*)) 有什么问题? (fill-pointer *d*) =&gt; 8
  • 我没想到。它是否涉及对数组中所有单元格的额外复制操作?我正在测试这个。
  • @ThomasHoullier:是的,这会创建一个新向量并在那里复制数据。
  • 好吧,我写了一个快速测试,确实声明这个新向量的操作的执行时间与数组的大小成线性关系。

标签: vector merge common-lisp fill-pointer


【解决方案1】:

确实没有简单的方法可以得到merge 返回 vector 和 填充指针。

但是,您可以将向量替换到结果中:

(defparameter *c* (merge '(vector t) *a* *b* #'<))
(type-of *c*)
==> (SIMPLE-VECTOR 8)
(defparameter *d* (make-array (length *c*) :displaced-to *c* :fill-pointer t))
(type-of *d*)
==> (VECTOR T 8)
*d*
==> #(0 1 2 3 4 5 6 7)
(array-displacement *d*)
==> #(0 1 2 3 4 5 6 7); 0
(vector-push-extend 17 *d*)
==> 8
*d*
==> #(0 1 2 3 4 5 6 7 17)

到目前为止一切都很好,对吧?

不,没那么快:

(array-displacement *d*)
==> NIL; 0

当我们打电话给vector-push-extend*d* 上,它从一个置换数组转换为一个普通数组 因为底层simple-vector 无法扩展。

如果您愿意,您实际上可以考虑使用列表而不是数组 使用merge,因为它在列表上效率更高(重用 结构)。

【讨论】:

  • 感谢您的回答。确实,在我这端,第一次拨打vector-push-extend 需要付出巨大的代价。我想我必须按照您的建议切换到列表或不使用 merge
猜你喜欢
  • 1970-01-01
  • 2010-12-09
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2011-08-04
  • 2019-12-19
  • 2012-02-07
相关资源
最近更新 更多