我目前正在Clojure中实现一个小型解析器,它需要一个输入字符串,如:
aaa(bbb(ccc)ddd(eee))fff(ggg)hhh
并返回不包含括号内字符的字符串,即。
(bbb(ccc)ddd(eee))(ggg)
我编写了以下函数:
(defn- parse-str [input]
(let [bracket (atom 0)
output (atom [])]
(doseq [ch (seq input)]
(case ch
\( (swap! bracket inc)
\) (swap! bracket dec)
nil)
(if (or (> @bracket 0) (= ch \)))
(swap! output conj ch)))
(apply str @output)))
这对我来说很有用:
(parse-str"aaa(bbb(ccc)ddd(eee))fff(ggg)hhh")
“(bbb(ccc)ddd(eee))(ggg)”
然而,我担心我的方法过于面向对象,因为它使用原子作为某种局部变量来保持解析器的当前状态。
是否可以从功能性更强的编程角度编写相同的函数?(避开原子?)
任何意见,以改善我的代码也表示感谢。
这是函数的迭代版本;但它仍然是纯功能的。我发现这样的代码布局很容易阅读。记住,当使用递归时,总是先检查终止条件。
(defn parse-str [s]
(loop [[x & xs] (seq s), acc [], depth 0]
(cond
(not x) (clojure.string/join acc)
(= x \() (recur xs (conj acc x) (inc depth))
(= x \)) (recur xs (conj acc x) (dec depth))
(<= depth 0) (recur xs acc depth)
:else (recur xs (conj acc x) depth))))
在许多使用局部变量的情况下,您只需将任何变化的变量作为参数循环,从而使用递归而不是突变。
(defn- parse-str [input]
;; Instead of using atoms to hold the state, use parameters in loop
(loop [output []
bracket 0
;; The [ch & tail] syntax is called destructuring,
;; it means let ch be the first element of (seq input),
;; and tail the rest of the elements
[ch & tail] (seq input)]
;; If there's no elements left, ch will be nil, which is logical false
(if ch
(let [bracket* (case ch
\( (inc bracket)
\) (dec bracket)
bracket)
output* (if (or (> bracket* 0) (= ch \)))
(conj output ch)
output)]
;; Recurse with the updated values
(recur output* bracket* tail))
;; If there's no characters left, apply str to the output
(apply str output))))
两种方法:可以使用显式递归或reduce。
(defn parse-str [input]
(letfn [(parse [input bracket result]
(if (seq input)
(let [[ch & rest] input]
(case ch
\( (recur rest (inc bracket) (conj result ch))
\) (recur rest (dec bracket) (conj result ch))
(recur rest bracket (if (> bracket 0)
(conj result ch)
result))))
result))]
(clojure.string/join (parse input 0 []))))
(defn parse-str [input]
(clojure.string/join
(second (reduce (fn [acc ch]
(let [[bracket result] acc]
(case ch
\( [(inc bracket) (conj result ch)]
\) [(dec bracket) (conj result ch)]
[bracket (if (> bracket 0)
(conj result ch)
result)])))
[0 []]
input))))
我有一个输入json字符串,其中包含几个已经转义的特殊字符和一些未转义的特殊字符(如en-dash/em-dash)。解析此json字符串(需要解析此字符串以检索对象数组)后,它将具有特殊字符的字符串转换为Unicode值(例如,将短划线字符转换为2013)。我的要求是不要转义任何特殊字符,并保持其他已转义字符不变。简单来说,在解析JSON字符串后,内容不应更改。 请建议一些方法来处理这个问题。
我们正在使用dexguard,并且在dexguard项目中还具有以下设置。文本 我还尝试了提供res/值/字符串的变体。类似xml的: 和 等 在小路上。但字符串的键值正在变得模糊。 正在返回0。(其中key是字符串值)。 我也试过了 避免字符串OBF指令的正确方法是什么?
问题内容: 我想问一个有关在Java中避免字符串重复的问题。 该 情境 是:以标签和属性像这样的一个XML: 使用JibX,此XML将在如下所示的类中进行编组/解组: 该程序是长时间的批处理,因此将创建,使用,复制产品对象。 好吧, 问题 是:当我使用 Eclipse内存分析器(MAT)之 类的软件分析执行时,我发现了几个重复的String。例如,在id属性中, PROD 值在2000个实例左右重
问题内容: 我有这样的XML字符串 我遵循此帮助 用Java查询XML的最简单方法 我的代码: 我想获取味精节点值,但出现异常 我不会为这个简单的任务使用一些外部库。请指导我如何获取其他节点的值。谢谢 问题答案: 您不能将其重复用于多个调用,因为它会自动关闭。因此,您将获得IO异常。试试这个 编辑: 更好的方法是使用A解析您的XML并构建第一个(使用JAXP的DOM API),然后可以在多个XPa
问题内容: 我正在处理一种加密货币RPC并接收json数据,如下所示: 使用Jsoncpp库或json11会将数字解析为。发生这种情况时,由于双重精度问题,结果为:。总的来说,这对金融交易来说是灾难性的,是不可接受的。 我已经有一个定点库,可以使用有效的字符串并将其在内部视为整数。有没有一种方法可以使Jsoncpp(或其他任何json库)将选定的数字json值用作字符串,以便可以使用固定精度正确地
我正在尝试转义字符串中的XML特殊字符。转义由静态方法处理,如下所示。 现在,这种实现的问题是,我得到了一段字符串,它可能被解析,也可能不被解析。这导致输出不规则。 例如: 现在,为了得到正确的响应,我计划在静态方法中引入一个检查。通过使用if条件,如下所示。 这是一种正确的实施方式吗?如果不是,请提出建议?