新手球拍编码器。
我有一个xexpr,我想在它们位于某些标签旁边时过滤换行符。我的想法是,我希望在某些元素之前和之后避免使用新行,例如'eq
标记或'figure
标记。
假设我有以下内容:
(define tx1
'(div (div "this is" "\n\n" (eq "y=x") "\n\n" "my equation" (eq "z=y"))
"to fire" (eq "h=u") "up" "\n\n\n" (eq "tm=re") "\n" "this test" "\n"))
我想删除"\n"
标记周围的换行符字符串{"\n\n"
,"\n\n\n"
,'eq
)以生成以下内容:
(define result
'(div (div "this is" (eq "y=x") "my equation" (eq "z=y"))
"to fire" (eq "h=u") "up" (eq "tm=re") "this test" "\n"))
我的第一步是识别换行符。我发现模式匹配是一种可能的解决方案。
(match tx1
[(list a ... (regexp #rx"^\n+") b ...) `(,@a ,@b)]
[(list a ...) `(,@a)])
但是,每次出现换行时,我都必须运行一次匹配函数。在这种情况下,我必须运行它3次。我可以每次测试结果,看看它是否已经改变,但这似乎是次优的。
我还没有达到的第二步是将之前和之后的项目(a
和b
)与'eq
标记的列表进行匹配。第三步是找到子列表并递归这些。
我的问题是,首先是有更好的方法来解决这类问题吗?我相信可能有这样的解决方案。我的第二个问题是,如果匹配最好,是否有办法进行多次替换?我玩过缺点匹配,这在一定程度上有效,但它丢弃了第一项。
谢谢。
答案 0 :(得分:0)
我相信我找到了另一种解决方案。模式匹配是一个有趣的想法 - 它就像列表和表达式的正则表达式。但是,从新手的角度来看,它可以使用一些开发,使其与传统的正则表达式更紧密地对齐,例如搜索和替换函数等。
最终的解决方案是将输入xexpr转换为向量,并根据前面和前面的元素处理每个元素。
(define (clean-newlines elems [tags '(eq figure)])
(define elements (merge-newlines elems))
(define elems-vec (list->vector elements))
(for/list ([(elem idx) (in-indexed elems-vec)])
(cond
; skip first and last elements
[(or (= idx 0) (= idx (sub1 (vector-length elems-vec)))) elem]
; process recursively if elem is a txexpr
[(txexpr-elements? elem) (clean-newlines elem)]
; see if the element is a new line
[(and (string? elem) (regexp-match #rx"^\n+" elem))
; get the previous and next elements
(let ([prev (vector-ref elems-vec (sub1 idx))]
[next (vector-ref elems-vec (add1 idx))])
; if the previous or next element matches the tag, strip it
(cond
[(and (txexpr-elements? next) (member (get-tag next) tags)) "\n"]
[(and (txexpr-elements? prev) (member (get-tag prev) tags)) "\n"]
[else elem]))]
[else elem])))