多次匹配球拍模式

时间:2017-12-14 16:50:29

标签: pattern-matching racket

新手球拍编码器。

我有一个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次。我可以每次测试结果,看看它是否已经改变,但这似乎是次优的。

我还没有达到的第二步是将之前和之后的项目(ab)与'eq标记的列表进行匹配。第三步是找到子列表并递归这些。

我的问题是,首先是有更好的方法来解决这类问题吗?我相信可能有这样的解决方案。我的第二个问题是,如果匹配最好,是否有办法进行多次替换?我玩过缺点匹配,这在一定程度上有效,但它丢弃了第一项。

谢谢。

1 个答案:

答案 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])))