Clojure技术集合

Clojure 实现通配符匹配

2017-06-15  本文已影响96人  BlindingDark
(defn cutting
    [str result]
    (if (empty? str)
        result
        (recur (rest str) (conj result str))))
(defn cutting-string 
    [string]
    (map #(apply str %) (cutting string [])))

(defn star-end-pattern
  "匹配结尾是星号的情况"
  [pattern pattern-point]
  (if (and (< pattern-point (count pattern))
           (= \* (nth pattern pattern-point)))
    (recur pattern (inc pattern-point))
    (>= pattern-point (count pattern))))

(defn next-star-point
  "获得最右方的星号位置"
  [pattern pattern-point]
  (cond (>= (inc pattern-point) (count pattern))
        pattern-point,
        (= \* (nth pattern (inc pattern-point)))
        (recur pattern (inc pattern-point)),
        (not= \* (nth pattern (inc pattern-point)))
        pattern-point))

(defn match
  "匹配带通配符的字符串"
  [pattern string pattern-point string-point]
  (let [str-length (count string),
        pattern-length (count pattern)]
    (cond
      (>= string-point str-length)                          ;;字符串到了末尾(结束)的情况,可以继续被 * 匹配
      (star-end-pattern pattern pattern-point),

      (>= pattern-point pattern-length) false,              ;;如果匹配串结束但是字符串没有结束

      (= \* (nth pattern pattern-point))                    ;; 通配符匹配
      (let [p-behind-star (subs pattern (inc (next-star-point pattern pattern-point))),
            strs (cutting-string (subs string string-point str-length)),
            result (map #(match p-behind-star % 0 0)
                        (cutting-string (subs string string-point str-length)))]
            (not (empty? (filter true? result))))

      (not= (nth pattern pattern-point) (nth string string-point)) false, ;;非通配符匹配失败

      :else (recur pattern string (inc pattern-point) (inc string-point)))))

(defn match-filename
  [fmt file]
  (match fmt file 0 0))

简单测试

(match-filename "*a*b" "aababa")
=> false
(match-filename "*a*b" "aaab")
=> true
(match-filename "*a*b" "aabab")
=> true
(match-filename "*a*b*" "aabab")
=> true
(match-filename "*a*b*" "ab")
=> true
上一篇 下一篇

猜你喜欢

热点阅读