我是lisp的新手,我试图在数组中交换两个元素。我想知道是否有一个函数来获取指定的位置,所以我可以使用rotatef来交换它们。
我已尝试过功能位置,但它不适用于数组,因为它不是一个序列。
如果没有针对数组的内置函数,最佳计算解决方案是什么?
我已经四处搜索,似乎无法找到一个简单的解决方案。行主要是解决方案吗?
基本上,我想在二维数组中找到一个元素的位置并返回在rotatef中使用的位置
答案 0 :(得分:3)
您可以创建一维位移数组,并将其用作position
的矢量。
示例:
CL-USER 9 > (let ((a0 (make-array '(2 3)
:initial-contents '((foo1 bar foo2)
(foo3 baz foo4)))))
(let ((a1 (make-array (reduce #'+ (array-dimensions a0))
:displaced-to a0)))
(let ((pos1 (position 'baz a1))
(pos2 (position 'bar a1)))
(when (and pos1 pos2)
(rotatef (aref a1 pos1)
(aref a1 pos2)))))
a0)
#2A((FOO1 BAZ FOO2) (FOO3 BAR FOO4))
答案 1 :(得分:1)
我认为它应该有用 - 数组确实是序列。
(let* ((an-array (make-array 6 :initial-contents '(#\f #\o #\o #\b #\a #\r)))
(f-pos (position #\f an-array))
(r-pos (position #\r an-array)))
(rotatef (elt an-array f-pos)
(elt an-array r-pos))
an-array)
;=> #(#\r #\o #\o #\b #\a #\f)
当然,您不需要将职位绑定到名称。这也有效:
(let ((an-array (make-array 6 :initial-contents '(#\f #\o #\o #\b #\a #\r))))
(rotatef (elt an-array (position #\f an-array))
(elt an-array (position #\r an-array)))
an-array)
;=> #(#\r #\o #\o #\b #\a #\f)
如果问题是position
找不到您需要的元素,则其:test
参数可能会有所帮助。还有position-if
和position-if-not
函数可以让您提供自己的谓词来识别元素。所有三个都在HyperSpec中描述here。
这是一个可能在没有:test
参数的情况下无法工作的示例,因为默认值(对于带有:test
参数的所有序列函数都是eql
- 有关标准序列函数关键字参数的一个很好的摘要,请参见表11-2 here。不在列表上工作。
(let ((an-array (make-array 3 :initial-contents '((1 2 3)
(4 5 6)
(7 8 9)))))
(rotatef (elt an-array (position '(1 2 3) an-array :test #'equal))
(elt an-array (position '(7 8 9) an-array :test #'equal)))
an-array)
;=> ((7 8 9) (4 5 6) (1 2 3))
(在SBCL 1.0.55.0.debian上测试)。
<强>加了:强>
这是一种使用二维数组进行蛮力的方法。 find-position
假设数组的大小为(3 3)
,但很容易让它变得更加通用。
我不主张将此作为最佳解决方案,但在误解了您的问题之后,我并不想空手而归:)
(defvar an-array #2A((1 2 3) (4 5 6) (7 8 9)))
(defun find-position (array item &key (test #'eql))
(loop for i below 3 do
(loop for j below 3 do
(when (funcall test (aref array i j) item)
(return-from find-position (list i j))))))
(defun swap-4-and-7 (array)
;; Example use
(destructuring-bind (i1 j1) (find-position array 4)
(destructuring-bind (i2 j2) (find-position array 7)
(rotatef (aref array i1 j1)
(aref array i2 j2))))
array)
(swap-4-and-7 an-array)
;=> #2A((1 2 3) (7 5 6) (4 8 9))