如果我有一个像...
(def test [[1 2 3]
[4 5 6]
[7 8 9]])
我想要5的索引(这将是(1,1))我该怎么做?所以(找到 5 个测试)= (1,1)
使用列表推导(for)可以找到所有匹配位置的列表:
(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 mat->map
[mat]
(into {} (for [[i row] (map-indexed vector mat)
[j key] (map-indexed vector row)]
[key [i j]])))
我同意 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)])
我定义了一个函数 indexof 来查找给定序列中元素的索引。该函数将首先创建一个索引和值的向量。然后将结果反转,以便您拥有要索引的值映射。请注意,此功能仅在您的列表中有独特元素时才有效。我假设这些数字在您的问题中是唯一的(如果我错了,请纠正我)。
后面的 clojure 语句将展平列表并找到给定元素的索引并将索引转换为 2d 索引。
这应该做你想要的:
(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 中的问题表明您可能从错误的角度处理问题。上面的函数不应该用于高性能矩阵计算,但除非另有考虑,否则它具有足够的性能。