如果我有一个像这样的列表...
(def test [[1 2 3]
[4 5 6]
[7 8 9]])
我希望找到数字5在一个测试集合中的索引位置,即(1,1)。如何实现呢?
代码示例:(find 5 test) = (1,1)
(def test [[1 2 3][4 5 6][7 8 9]])
(for [[x row] (map-indexed vector test)
[y val] (map-indexed vector row)
:when (= 5 val)]
[x y])
=> ([1 1])
编辑:使用解构在 'for' 函数中起作用。
我认为没有内置函数可以完成这个操作,但编写一个函数应该不难。
您可以将嵌套的向量展平为单个列表,然后搜索,获取结果索引并使用第一个嵌套向量的长度拆分出x和y坐标。
(defn find2d [data item]
(let [n (count (first data))
i (.indexOf (flatten data) item)]
(if (pos? i)
(list (quot i n) (mod i n)))))
(find2d data 5) ;=> (1 1)
这应该可以满足你的需求:
(defn indexof-2D [item mat]
(letfn [(index-of-row
[x]
(first (keep-indexed #(if (= item %2) %1) x)))]
(->> mat
(map-indexed #(vector %1 (index-of-row %2)))
(filter last)
first)))
现在我不知道你的使用情况是什么,但通常在Clojure中使用索引来解决问题意味着你可能从错误的角度来处理问题。上述函数不应该用于高性能矩阵计算,但在被认为需要改进之前,它已经足够高效。
我同意mortalapeman的观点,你可能从错误的角度来解决问题。我对八数码问题上的A*搜索并不了解,因此我不会尝试去解决它。
但是我会以下面的方式来寻找一个二维列表的索引:
(defn indexof [y xs]
(last (find (clojure.set/map-invert (map-indexed vector xs)) y)))
(let [i (indexof 5 (flatten test))]
[(int (/ i 3)) (mod i 3)])
(defn mat->map
[mat]
(into {} (for [[i row] (map-indexed vector mat)
[j key] (map-indexed vector row)]
[key [i j]])))
mat
是一个大型或无限序列,它就不会扩展。 - M Smith