【问题标题】:Get string values from vector从向量中获取字符串值
【发布时间】:2016-06-03 00:58:51
【问题描述】:

我有这个字符串向量:

["Color: Black" "Color: Blue" "Size: S" "Size: XS"]

如何获取colorSize 的所有值?

例如,输出应该是 ["color" ["Black" "Blue"]]

【问题讨论】:

    标签: dictionary vector clojure


    【解决方案1】:

    此解决方案按属性名称(颜色、大小等)拆分每个字符串、分组,然后清理预期值:

        user=> (require '[clojure.string :as string])
        nil
    
        user=> (def attributes ["Color: Black" "Color: Blue" "Size: S" "Size: XS"])
        #'user/attributes
    
        user=> (as-> attributes x
          #_=>   (map #(string/split % #": ") x)
          #_=>   (group-by first x)
          #_=>   (reduce-kv #(assoc %1 %2 (mapv second %3)) {} x))
        {"Color" ["Black" "Blue"], "Size" ["S" "XS"]}
    

    【讨论】:

    • as-> 宏的巧妙使用。
    • as-> 可以很容易地替换为->>,因为x 是所有形式中的最后一个参数。此外,对集合进行 3 次完整传递(mapgroup-byreduce-kv + mapv 对于每个组),更不用说一堆中间集合,看起来真的是多余的。因此,展示 clojure 序列函数的强大功能是一个很好的答案,但如果您想在生产环境中实际使用它,那真的很糟糕。
    • @leetwinski 我同意你的大部分观点。我开始使用as-> 是因为它的清晰度和灵活性(当我想添加一个不符合其他步骤的参数顺序的步骤时,我可以这样做)。我认为这个解决方案以多次通过为代价很好地展示了每一步。
    • @CurtisSummers,同意as-> 用于不同的聚集位置(毕竟这是它的主要目的),但在这种情况下,我会说它有点混淆。海事组织
    【解决方案2】:

    我宁愿用reduce 一次性完成(因为它更短并且可能更快):

    user> (require '[clojure.string :as cs])
    nil
    
    user> (def data ["Color: Black" "Color: Blue" "Size: S" "Size: XS"])
    #'user/data
    
    user> (reduce #(let [[k v] (cs/split %2 #": ")]
                     (update %1 k (fnil conj []) v))
                  {} data)
    {"Color" ["Black" "Blue"], "Size" ["S" "XS"]}
    

    【讨论】:

    • 我喜欢这个答案,也许比我的更喜欢。与大多数 Clojure 序列函数一样,您通常可以将它们归结为 reduce 传递。但是,我认为除非您习惯于从 reduce 的角度思考,否则最初得出这个解决方案会比较困难。
    • 我猜是这样,但无论如何,当你选择 FP 路径时,习惯 reduce/fold 是一种“必要的邪恶”)(我的意思是理解的过程,这可能根据我的经验,真的很痛苦)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多