【问题标题】:Which is the most clojuresque way to compare characters and string? (single char string)比较字符和字符串的最流行的方式是什么? (单个字符字符串)
【发布时间】:2010-10-19 17:09:43
【问题描述】:

我想知道在 Clojure 中比较字符和字符串的最佳(clojuresque)方法是什么。 显然,这样的事情会返回 false:

(= (first "clojure") "c")

因为 first 返回一个 java.lang.Character 而“c”是一个单一的字符串。是否存在直接比较 char 和 string 而不调用强制转换的构造?我没有找到与此不同的方法:

(= (str (first "clojure")) "c")

但我不满意。 有任何想法吗? 再见, 阿尔弗雷多

【问题讨论】:

    标签: string clojure character


    【解决方案1】:

    直接的字符串互操作怎么样?

    (= (.charAt "clojure" 0) \c)

    (.startsWith "clojure" "c")

    它应该尽可能快,并且不分配 seq 对象(在您的第二个示例中是一个附加字符串),该对象会立即再次被丢弃以进行比较。

    【讨论】:

    • 我喜欢 Clojure 的一点是它不会在不需要的时候隐藏 Java,所以 +1。
    【解决方案2】:

    字符文字是在 Clojure 中编写的 \a \b \c ...,因此您可以简单地编写

    (= (first "clojure") \c)
    

    【讨论】:

    • 好的,但这只会将问题从字符串转移到字符。我的意思是,如果我需要输入单个字符串,为了比较我需要输入的字符串char :) 然而这是一个很好的提示,我不知道我可以使用 \c 来表达 char。谢谢^^
    【解决方案3】:

    可以直接索引字符串,而无需从那时起构建序列并获取该序列的第一个。

    (= (nth "clojure" 0) \c) 
    => true
    

    第 n 次调用此 java 代码:

    static public Object nth(Object coll, int n){
        if(coll instanceof Indexed)
            return ((Indexed) coll).nth(n);    <-------
        return nthFrom(Util.ret1(coll, coll = null), n);
    }
    

    直接有效地读取字符。

    首先调用这个java代码:

    static public Object first(Object x){
        if(x instanceof ISeq)
            return ((ISeq) x).first();
        ISeq seq = seq(x);    <----- (1)
        if(seq == null)
            return null;
        return seq.first();   <------ (2)
    }
    

    为字符串 (1) 构建一个 seq(构建一个 seq 非常快),然后从该 seq (2) 中获取第一项。返回后seq是垃圾。

    Seq 显然是在 clojure 中访问任何序列的最惯用的方式,我根本不会敲它们。了解您何时创建的内容很有趣。将所有对first 的调用切换为对nth 的调用可能是过早优化的情况。 如果你想要字符串中的第 100 个字符,我建议使用索引访问函数,例如 nth

    简而言之:不要为小事出汗:)

    【讨论】:

      【解决方案4】:

      从根本上说(至少在 Clojure 级别上——尽管请参阅 Kotarak's answer 和其他人的替代方案),您正在比较两个序列:“clojure”和“c”。相等的条件是每个序列的第一个元素相等。因此,如果您想直接表达这一点,您可以这样做

      (apply = (map first ["clojure" "c"]))
      

      或者反过来,你在每对字符之间的相等比较上创建一个惰性序列,然后只取它的第一个元素:

      (first (map = "clojure" "c"))
      

      【讨论】:

      • 您可以使用every? 将其扩展到任意前缀(阅读:类似于.startsWith):(every? identity (map = "clojure" "clo"))
      【解决方案5】:

      您可以使用 clojure.contrib.string 中的 take 函数。或者编写自己的函数来返回第一个字符,如果这是你经常需要的东西。

      【讨论】:

        【解决方案6】:

        您可以只使用 str,就像您在第二个示例中所做的那样。这并没有什么问题。我的意思是,您也可以先调用“c”以使其成为一个字符,但这不会真正产生影响。你有什么理由喜欢这个吗?通过在字符上调用 str 并没有真正为您的代码添加太多内容。

        【讨论】:

        • 没有什么特别的原因,我只是想知道如何管理字符和字符串的比较,而不用强制转换填充我的代码:)
        【解决方案7】:
        user=> (= (subs "clojure" 0 1) "c")
        true
        user=> (= (str (first "clojure") "c"))
        true
        

        【讨论】:

          【解决方案8】:

          如今,您不一定非得使用 Java 互操作:

          (clojure.string/starts-with? "clojure" "c")
          

          starts-with? 只是一个薄包装(.startsWith 周围)。

          现在,如果您同时使用 Clojure 和 ClojureScript,您就不必同时记住 Java 和 JavaScript 互操作。

          【讨论】:

            猜你喜欢
            • 2014-09-03
            • 1970-01-01
            • 1970-01-01
            • 2021-03-30
            • 1970-01-01
            • 2011-08-17
            • 2020-08-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多