Jadvallardan koordinatani olish

Bir qator ichidagi belgining koordinatalarini qanday topishim mumkinligini aniqlashda qiyinchiliklarga duch kelmoqdaman.

Menda shunday kichik ASCII xaritalari bor:

+-----+
|XPX X|
|X   X|
|X  XX|
|X   X|
|XX DX|
+-----+

Ushbu xarita chiziqlar bo'yicha qatorga bo'linadi, shuning uchun qator quyidagicha ko'rinadi:

["+-----+" "|XPX X|" "|X   X|" "|X  XX|" "|X   X|" "|XX DX|" "+-----+"]

Men nima qilishni xohlayotgan bo'lsam, "R" kabi bir belgi o'tishi va xaritadagi belgining koordinatasini topish. Bu holatda 'R' koordinatasida joylashgan (2,3).

Boshlanish nuqtasi sifatida men ishlatadigan belgining ustunini aniqlashga harakat qildim

(doseq [m map] (println (clojure.string/index-of m "P")))

Bu chiqishni qaytardi

nil
2
nil
nil
nil
nil
nil
nil

Shu nuqtada, men endi qaytib, «2» va ushbu satr ichidagi qator indeksini qanday qilib qaytarib olishimga aralashtiraman.

1

5 javoblar

Buni qilishning bir usuli - siz kiritganingizdek, kiritilgan matnning vektorini qabul qilsangiz, xuddi shunga o'xshash:

(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)))

Bu qidirayotgan narsangizning birinchi nusxasini qaytaradi, masalan. "+" uchun [0,0] bo'ladi. Bundan tashqari, (2,3) aslida (1,2), chunki clojure nolga asoslangan kataloglashni qo'llaydi.

You can shorten this a little by using keep with 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))))

EDIT:

Buning o'rniga kimligi bilan bir necha dan foydalaning (birinchi bo'lib (kimligini saqlang ....) ) bo'lishi kerakligini tushunib etdim:

(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)))

Quyida keltirilgan ba'zi javoblar sizning dastlabki emas, balki har bir muvofiq koordinatani olish uchun sizga yordam berdi. Buni amalga oshirish uchun faqat yuqoridagi versiyadagi nilni o'chirish uchun bir necha identifikatori kodini o'zgartirish kerak.

Misol uchun:

(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)))

Va nihoyat, agar siz indekslarni bitta asosda yaratmoqchi bo'lsangiz, har bir topilgan indeksni oshirishingiz mumkin:

(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)))
2
qo'shib qo'ydi
Ahhh Ha ... bu kod va kodni qisqartiradi. Jadvalda juda ko'p qulay funktsiyalar mavjud, ba'zida ularning hammasini xotirlashda muammo bor!
qo'shib qo'ydi muallif Solaxun, manba
Shuningdek qarang: keep-indexed
qo'shib qo'ydi muallif amalloy, manba
Bu juda yaxshi ishladi. Men amalloy tomonidan aytib o'tilganidek, uni saqlab qo'yish orqali qisqartirdim.
qo'shib qo'ydi muallif David Furnam, manba

Men biroz yura boshladim va charning barcha ko'rinishlarini koordinatalarini topadigan funksiya yozdim.

(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])
1
qo'shib qo'ydi
(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)"

The map-indexed loops through the row strings, searching each one for your substring while keeping track of the row index i. The some->> threading macro passes the result (which is a LazySeq) to the filter, which removes all elements with nil columns. Since we only want the first coordinates (assuming the character you're searching for can only exist once in the map), we select the first element. If the substring doesn't exist in the map, we will get nil, and the the some->> will short-circuit so that nil is returned. Otherwise, the indices will both be incremented (since your coordinates are 1-indexed.

Shu bilan bir qatorda siz o'zingizning xaritangizni lineerlashtirasiz, chiziqli xaritada indeksni topishingiz va keyin 2d koordinatalarini lineer indekslardan hisoblashingiz mumkin:

(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))))))))
1
qo'shib qo'ydi

Hammasini qanday topishini ko'rsatish uchun boshqa P char qo'shdim. Bu erda for yordamida oddiy echim:

(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])))

natijasi:

(find-chars-2 data-array \P))  => ([1 2] [4 3])

Using get-in assumes you have nested vectors, hence the need for strs->array. We also assume the data is rectangular (not ragged) and haven't put in any error-checking that a real solution would need.

0
qo'shib qo'ydi

men bunga o'xshash narsa bilan borishni xohlayman (biroz ko'proq umumlashtirilgan)

(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])

ikkinchisi esa ko'proq funktsional (kamroq o'qilishi mumkin bo'lsa-da)

(defn find-2d [pred field]
  (filter (comp pred last)
          (mapcat #(map vector (repeat %1) (range) %2)
                  (range)
                  field)))

Birinchisi bilan bir xil ishlaydi

0
qo'shib qo'ydi