我无法弄清楚如何在数组中找到一个字符的坐标。
我有一些小的ASCII地图,如下所示:
+-----+
|XPX X|
|X X|
|X XX|
|X X|
|XX DX|
+-----+
此地图按行分成数组,因此数组如下所示:
["+-----+" "|XPX X|" "|X X|" "|X XX|" "|X X|" "|XX DX|" "+-----+"]
我要做的是传递一个像P' P'并找出地图中角色的坐标。在这种情况下,P' P'位于坐标(2,3)。
作为一个起点,我尝试使用
找出角色的列(doseq [m map] (println (clojure.string/index-of m "P")))
这返回了
的输出nil
2
nil
nil
nil
nil
nil
nil
在这一点上,我现在很困惑,我怎么能回归' 2'以及该行所在的数组索引。
答案 0 :(得分:2)
一种方法 - 假设你的输入是你所呈现的字符串向量,就像这样:
(def the-map ["+-----+" "|XPX X|" "|X X|" "|X XX|" "|X X|" "|XX DX|" "+-----+"])
(defn get-index [item coll]
(some #(when ((complement nil?) %) %)
(map-indexed (fn [ix x] (let [i (clojure.string/index-of x item)]
(when i [ix i])))
coll)))
这将返回您要查找的任何项目的第一个实例,例如对于“+”,它将是[0,0]
。另外(2,3)实际上是(1,2),因为clojure使用从零开始的索引。
您可以将keep
与identity
(defn get-index [item coll]
(first (keep identity
(map-indexed (fn [ix x] (let [i (clojure.string/index-of x item)]
(when i [ix i])))
coll))))
修改强>
我意识到拥有(first (keep identity....)
是多余的,而只需将some
与identity
一起使用:
(defn get-index [item coll]
(some identity
(map-indexed (fn [ix x] (let [i (clojure.string/index-of x item)]
(when i [ix i])))
coll)))
下面的一些答案为您提供了获得每个匹配坐标的方法,而不是第一个。您只需在我的上述版本中将some identity
更改为remove nil?
即可完成此操作。
例如:
(defn get-index [item coll]
(remove nil?
(map-indexed (fn [ix x] (let [i (clojure.string/index-of x item)]
(when i [ix i])))
coll)))
最后,如果您真的打算让索引基于一个,那么您只需递增每个找到的索引:
(defn get-index [item coll]
(some identity
(map-indexed (fn [ix x] (let [i (clojure.string/index-of x item)]
(when i [(inc ix) (inc i)])))
coll)))
答案 1 :(得分:1)
(def strmap ["+-----+" "|XPX X|" "|X X|" "|X XX|" "|X X|" "|XX DX|" "+-----+"])
(defn find-char-2d
[arr char-to-find]
(some->> (map-indexed (fn [i row]
[i (clojure.string/index-of row char-to-find)])
arr)
(filter second)
first
(map inc)))
(println (find-char-2d strmap "Q")) ; prints "nil"
(println (find-char-2d strmap "P")) ; prints "(2, 3)"
map-indexed
循环遍历row
字符串,搜索每个字符串以查找子字符串,同时跟踪行索引i
。 some->>
线程宏将结果(LazySeq
)传递给filter
,后者会删除nil
列的所有元素。由于我们只想要第一个坐标(假设您要搜索的字符只能在地图中存在一次),我们选择第一个元素。如果地图中不存在子字符串,我们将获得nil
,some->>
将短路,以便返回nil
。否则,索引将递增(因为您的坐标是1索引。
或者,您可以线性化地图,在线性地图中找到索引,然后从线性索引计算2d坐标:
(defn find-char-2d
[arr char-to-find]
(some-> (clojure.string/join "" arr)
(clojure.string/index-of char-to-find)
((juxt #(-> (/ % (count arr)) int inc)
#(inc (mod % (count (first arr))))))))
答案 2 :(得分:1)
我更进一步,写了一个函数,找到所有出现的char的坐标。
(let [a ["+-----+" "|XPX X|" "|X X|" "|X XX|" "|X X|" "|XX DX|" "+-----+"]]
(letfn [(find-coords [a ch]
(let [op (fn [f] (comp inc #(f % (count (first a)))))]
(->> a
(clojure.string/join "")
(map-indexed vector)
(filter (comp (partial = ch) second))
(map first)
(map (juxt (op quot) (op rem))))))]
(find-coords a \P)))
=> ([2 3])
(find-coords a \X)
=> ([2 2] [2 4] [2 6] [3 2] [3 6] [4 2] [4 5] [4 6] [5 2] [5 6] [6 2] [6 3] [6 6])
答案 3 :(得分:0)
我添加了另一个P
字符,以显示如何找到所有这些字符。以下是使用for
:
(defn strs->array [strs] (mapv vec strs))
(def data ["+-----+"
"|XPX X|"
"|X X|"
"|X XX|"
"|X P X|"
"|XX DX|"
"+-----+"])
(def data-array (strs->array data))
(defn find-chars-2 [ch-array tgt-char]
(let [num-rows (count ch-array)
num-cols (count (first ch-array))]
(for [ii (range num-rows)
jj (range num-cols)
:let [curr-char (get-in ch-array [ii jj])]
:when (= tgt-char curr-char)]
[ii jj])))
结果:
(find-chars-2 data-array \P)) => ([1 2] [4 3])
使用get-in
假设您有嵌套向量,因此需要strs->array
。我们还假设数据是矩形的(没有参差不齐),并且没有进行任何真正的解决方案需要的错误检查。
答案 4 :(得分:0)
我会选择这样的事情(更广义)
(def field ["+-----+"
"|XPX X|"
"|X ZX|"
"|X XX|"
"|X X|"
"|XX DX|"
"+-----+"])
(defn find-2d [pred field]
(for [[i line] (map-indexed vector field)
[j ch] (map-indexed vector line)
:when (pred ch)]
[i j ch]))
user> (find-2d #{\P} field)
;;=> ([1 2 \P])
user> (find-2d #{\P \Z} field)
;;=> ([1 2 \P] [2 4 \Z])
user> (find-2d #{\D \P \Z} field)
;;=> ([1 2 \P] [2 4 \Z] [5 4 \D])
user> (find-2d #(Character/isUpperCase %) field)
;;=> ([1 1 \X] [1 2 \P] [1 3 \X] [1 5 \X]
;; [2 1 \X] [2 4 \Z] [2 5 \X] [3 1 \X]
;; [3 4 \X] [3 5 \X] [4 1 \X] [4 5 \X]
;; [5 1 \X] [5 2 \X] [5 4 \D] [5 5 \X])
另一个更具功能性(虽然可读性较差)
(defn find-2d [pred field]
(filter (comp pred last)
(mapcat #(map vector (repeat %1) (range) %2)
(range)
field)))
与第一个完全相同