And*_*rew 7 algorithm vector clojure
假设我有一个向量["a" "b" "c" "a" "a" "b"].如果给定一个序列["a" "b"],我该如何删除该序列的所有实例(按顺序)?在这里,结果就是["c" "a"].
如果事先知道需要删除的序列,则core.match可能对您的任务有用:
(require '[clojure.core.match :refer [match]])
(defn remove-patterns [seq]
(match seq
["a" "b" & xs] (remove-patterns xs)
[x & xs] (cons x (remove-patterns xs))
[] ()))
(remove-patterns ["a" "b" "c" "a" "a" "b"]) ;; => ("c" "a")
Run Code Online (Sandbox Code Playgroud)
简短的回答是将其视为字符串并执行正则表达式删除:
(defn remove-ab [v]
(mapv str (clojure.string/replace (apply str v) #"ab" "")))
(remove-ab ["a" "b" "c" "a" "a" "b"])
=> ["c" "a"]
Run Code Online (Sandbox Code Playgroud)
很长的答案是通过迭代序列,识别匹配并返回没有它们的序列来实现自己的正则表达式状态机.
Automat可以帮助您制作自己的低级正则表达式状态机:https: //github.com/ztellman/automat
Instaparse可用于制作丰富的语法:https: //github.com/Engelberg/instaparse
你真的不需要一个用于这么小的匹配的库,你可以将它实现为循环:
(defn remove-ab [v]
(loop [[c & remaining] v
acc []
saw-a false]
(cond
(nil? c) (if saw-a (conj acc "a") acc) ;; terminate
(and (= "b" c) saw-a) (recur remaining acc false) ;; ignore ab
(= "a" c) (recur remaining (if saw-a (conj acc "a") acc) true) ;; got a
(and (not= "b" c) saw-a) (recur remaining (conj (conj acc "a") c) false) ;; keep ac
:else (recur remaining (conj acc c) false)))) ;; add c
Run Code Online (Sandbox Code Playgroud)
但是,正确处理所有条件可能会非常棘手......因此正式的正则表达式或状态机是有利的.
或者递归定义:
(defn remove-ab [[x y & rest]]
(cond
(and (= x "a") (= y "b")) (recur rest)
(nil? x) ()
(nil? y) [x]
:else (cons x (remove-ab (cons y rest)))))
Run Code Online (Sandbox Code Playgroud)