【问题标题】:Replace the UUIDs with Strings用字符串替换 UUID
【发布时间】:2021-06-02 23:27:53
【问题描述】:

我想使用 Clojure 将 UUID 替换为字符串,但不知道如何为其创建函数。

这是原始值:/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964

并希望看到如下

/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id

但也足以处理以下示例,

案例 1。

输入

/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car

预期结果

/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car

案例 2。

输入

/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car

预期结果

/user-1/user-1-id/user-2/user-2-id/car

案例 3。

输入

/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car/tire

预期结果

/user-1/user-1-id/user-2/user-2-id/car/tire

【问题讨论】:

  • user-1-id 等从何而来?你能显示一些代码吗?
  • @AlanThompson:基本上当 URI 中有 /user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/ 时,UUID 应该替换为 / 之前的值加上附加 -id

标签: clojure


【解决方案1】:

或者直接做简单的字符串替换

(clojure.string/replace
 "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964"
 #"/(user-\d+)/[0-9a-f\-]+(?=/|$)"
 "/$1/$1-id")

;;=> "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id"

(defn normalize-path [path]
  (clojure.string/replace path #"/(user-\d+)/[0-9a-f\-]+(?=/|$)" "/$1/$1-id"))

(map normalize-path
     ["/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"
      "/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"
      "/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car/tire"])

;;=> ("/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
;;    "/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
;;    "/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car/tire")

您还可以更新正则表达式以仅匹配有效的 uid,如下所示:

(defn normalize-path [path]
  (clojure.string/replace
   path
   #"/(user-\d+)/[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}(?=/|$)"
   "/$1/$1-id"))

(map normalize-path
     ["/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"
      "/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"
      "/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car/tire"
      "/v2/user-101/asd-asd-asd/user-2/xxx"
      "/v3/user-404/aa44ddss-3333-4444-aaaa/user-505/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964"])

;; ("/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
;;  "/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
;;  "/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car/tire"
;;  "/v2/user-101/asd-asd-asd/user-2/xxx"
;;  "/v3/user-404/aa44ddss-3333-4444-aaaa/user-505/user-505-id")

【讨论】:

    【解决方案2】:

    这是一种方法,基于my favorite template project

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [tupelo.string :as str]
        [tupelo.uuid :as uuid]
        ))
    
    (defn replace-uuids
      [input-str]
      ; use `let-spy-pretty` below to see step-by-step results
      (let [segments       (str/split input-str #"/")
            pairs          (partition-all 2 segments)
            ; looks like:
            ;    [["" "v1"]
            ;     ["user-1" "4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964"]
            ;     ["user-2" "7badb866-44fc-43c7-9cf4-aa3c2f8cc964"]
            ;     ["user-3" "27ebd241-44fc-43c7-9cf4-aa3c2f8cc964"]]
            version-pair   (first pairs)
            user-pairs     (rest pairs)
            user-pairs-mod (for [pair user-pairs]
                             (let [user-part (first pair)
                                   uuid-part (second pair)]
                               (if (uuid/uuid-str? uuid-part)
                                 [user-part (str user-part "-id")]
                                 pair)))
            all-pairs-mod  (flatten [version-pair user-pairs-mod])
            result         (str/join (interpose "/" all-pairs-mod))]
        result))
    
    (dotest
      (is= "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id"
        (replace-uuids "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964"))
      (is= "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
        (replace-uuids "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"))
      )
    

    对于更通用的解决方案,您可能只想使用正则表达式,这是 uuid-str? 在内部所做的。

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [schema.core :as s]
        [tupelo.string :as str]
        ))
    
    (def full-regex
      #"(?x)              # expanded form
      /                   # a slash
      ([a-zA-Z0-9-_]+)    # repeated identifier char in a capture group
      /                   # a slash
      \p{XDigit}{8}       # 8 hex digits
      -                   # hyphen
      \p{XDigit}{4}       # 4 hex digits
      -                   # hyphen
      \p{XDigit}{4}       # 4 hex digits
      -                   # hyphen
      \p{XDigit}{4}       # 4 hex digits
      -                   # hyphen
      \p{XDigit}{12}      # 12 hex digits
      ")
    
    (s/defn replace-uuids :- s/Str
      [s :- s/Str]
      (str/replace s full-regex
        (fn [arg]
          (let ; use `let-spy` to see intermediate steps
            [x1     (second arg)
             result (str "/" x1 "/" x1 "-id")]
            result))))
    

    结果

    (dotest
      (is= "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id"
        (replace-uuids "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964"))
      (is= "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car"
        (replace-uuids "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car"))
      (is= "/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car/tire"
        (replace-uuids "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car/tire"))
      )
    

    另请参阅list of documentation sources

    【讨论】:

    • 我试图为这个/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964/car使用这个函数,它给了我这个结果/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id而不是这个/v1/user-1/user-1-id/user-2/user-2-id/user-3/user-3-id/car
    • 这就是你所说的你想要的!如果没有,请编辑并澄清问题。
    • 对不起,我应该正确解释。我已经用不同的案例更新了这个问题。我希望现在很清楚。
    • 我在我的[tupelo.string :as str] [tupelo.uuid :as uuid]:require 列表中添加了这些,但我仍然看到这个uuid/uuid-str? 无法解决
    • 确保将您的project.clj 更新为[tupelo "21.06.03b"]
    【解决方案3】:

    Clojure Spec 对这类事情很方便。这是一种方法:

    (require '[clojure.spec.alpha :as spec]
             '[clojure.string :as cljstr])
    
    (spec/def ::fixkey-format
      (spec/cat :root #{""}
                :version #{"v1"}
                :pref1 #{"user-1"}
                :user-1 string?
                :pref2 #{"user-2"}
                :user-2 string?
                :pref3 #{"user-3"}
                :user-3 string?))
    
    (defn replace-values [input new-values]
      (cljstr/join
       "/"
       (spec/unform
        ::fixkey-format
        (merge (spec/conform ::fixkey-format (cljstr/split input #"/")) new-values))))
    
    (replace-values "/v1/user-1/4bcbe877-44fc-43c7-9cf4-aa3c2f8cc964/user-2/7badb866-44fc-43c7-9cf4-aa3c2f8cc964/user-3/27ebd241-44fc-43c7-9cf4-aa3c2f8cc964"
                    {:user-1 "x"
                     :user-2 "y"
                     :user-3 "z"})
    ;; => "/v1/user-1/x/user-2/y/user-3/z"
    

    【讨论】:

      猜你喜欢
      • 2014-03-28
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 1970-01-01
      • 2023-03-04
      • 2011-06-13
      • 2013-05-01
      • 1970-01-01
      相关资源
      最近更新 更多