Clojure如何在2D列表中获取项目的索引

4
如果我有一个像这样的列表...
(def test [[1 2 3]
           [4 5 6]
           [7 8 9]])

我希望找到数字5在一个测试集合中的索引位置,即(1,1)。如何实现呢?

代码示例:(find 5 test) = (1,1)

5个回答

10
使用列表推导式(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' 函数中起作用。


2

我认为没有内置函数可以完成这个操作,但编写一个函数应该不难。

您可以将嵌套的向量展平为单个列表,然后搜索,获取结果索引并使用第一个嵌套向量的长度拆分出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)

很好,我更喜欢你的解决方案。我总是忘记与序列相关的Java方法。 - mortalapeman
不错!但是正如其他答案所建议的那样,我是否从错误的角度考虑了这个问题?如果您想在八数码谜题上进行A*搜索? - user2150839
我对所涉及的算法没有很强的掌握,但我认为你不需要像那样嵌套向量。你可以先使用一个平坦的向量和行长度。 - Jared314
谢谢你的帮助。我最初使用这个来计算从一个方格到另一个方格所需的移动次数。我想我应该找到另一种方法。 - user2150839

0

这应该可以满足你的需求:

(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中使用索引来解决问题意味着你可能从错误的角度来处理问题。上述函数不应该用于高性能矩阵计算,但在被认为需要改进之前,它已经足够高效。


我是Clojure的新手。我正在尝试使用它来帮助我解决八数码问题中的A*搜索。 - user2150839

0

我同意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索引。

0
作为一个通用解决方案,假设您最终想要获取嵌套序列中所有元素的索引,可以使用以下方式创建一个将所有元素映射到它们的索引的映射表:
(defn mat->map
  [mat]
  (into {} (for [[i row] (map-indexed vector mat)
                 [j key] (map-indexed vector row)]
             [key [i j]])))

对于 OP 中的 3x3 矩阵,这个方法效果很好。然而,如果 mat 是一个大型或无限序列,它就不会扩展。 - M Smith
@MSmith:是的,当然。如果您需要小矩阵中许多元素的索引,则这是一种有效的解决方案,但如果您只需要大矩阵中的几个元素,则不太适用。 - Rörd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接