我是新來的lisp,我試圖交換數組中的兩個元素。我想知道是否有函數獲取指定的位置,所以我可以使用rotatef來交換它們。Lisp數組元素交換
我試過函數的位置,但它不適用於數組,因爲它不是一個序列。
如果沒有數組的內置函數,什麼是最好的計算解決方案?
我周圍搜索,似乎無法找到一個簡單的解決方案。行是主要的解決方案嗎?
基本上,我想找到的元素的2維陣列中的位置,並返回所述位置在rotatef
我是新來的lisp,我試圖交換數組中的兩個元素。我想知道是否有函數獲取指定的位置,所以我可以使用rotatef來交換它們。Lisp數組元素交換
我試過函數的位置,但它不適用於數組,因爲它不是一個序列。
如果沒有數組的內置函數,什麼是最好的計算解決方案?
我周圍搜索,似乎無法找到一個簡單的解決方案。行是主要的解決方案嗎?
基本上,我想找到的元素的2維陣列中的位置,並返回所述位置在rotatef
,我認爲它應該工作 - 陣列確實序列。
(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))
要使用可以使一維移位陣列和使用,作爲用於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))
嗨賴,謝謝你的提示。這有效,但現在我不能有效地交換它們。我總是可以將位置轉回到數組座標以在rotatef上使用,但似乎不合邏輯。 此外,我如何從一維數組回到兩個維度? 無法循環訪問數組,並在找到nil時返回?我試着用(循環爲我從0到N做(循環從J從0到N do)(當(數組ij)無)(返回(列表ij))))但似乎不工作 – d0pe
@ d0pe:確定你可以很容易地交換它們,使用rotatef來移動它們,並且你不需要返回任何東西,位移的數組是一個新的數組,它引用原始數組。 –
似乎無法make-array'(3 3)和make-array 3之間有區別嗎?因爲我通過了一個make-array'(3 3),當我嘗試位置時它說它是一個非序列 我應該收到一個2維NxN數組和數字,並且想要發現零。在你的最後一個例子中,位置的作用是因爲你搜索的是一個列表,而不是列表中的數字,而不是2。在前兩個例子中,它們都是被認爲是序列並因此定位的矢量,但是如果它是2維的sional array lisp認爲它是非序列的 – d0pe
的確,這是真的。我沒有意識到你正在使用一個二維數組。你可能想要更明確地將它添加到你的問題中(雖然Rainer似乎已經理解了,所以也許它只是我!) – jbm
@ d0pe,我添加了一個蠻力方法,可以在二維數組上工作(類似於你考慮到你對Rainer的評論,我認爲)。我沒有機會在CL中使用多維數組,所以可能有更好的方法 - 我建議繼續研究Rainer的建議。 – jbm