代码之家  ›  专栏  ›  技术社区  ›  frankodwyer

如何优雅地计算ruby中单词的字谜签名?

  •  3
  • frankodwyer  · 技术社区  · 17 年前

    产生于 this 问题,我正在寻找一种优雅的(ruby)方法来计算中建议的单词签名 this 答复

    建议的想法是对单词中的字母进行排序,并对重复的字母进行游程编码。例如,“mississippi”首先变成“IIIIMPPSSS”,然后可以通过编码为“4impp4s”进一步缩短。

    我对ruby还比较陌生,虽然我可以一起破解一些东西,但我相信这对于那些对ruby有更多经验的人来说是一个简单的例子。我很想了解人们的方法,提高我的ruby知识。

    编辑:澄清一下,计算签名的性能对我的应用程序没有多大影响。我希望计算签名,这样我就可以将它与每个单词一起存储在一个大型单词数据库中(450K个单词),然后查询具有相同签名的单词(即给定单词的所有拼字法,即实际的英语单词)。因此,人们关注空间。“优雅”的部分只是为了满足我的好奇心。

    3 回复  |  直到 9 年前
        1
  •  6
  •   martinus    17 年前

    创建字母排序列表的最快方法是:

    "mississippi".unpack("c*").sort.pack("c*")
    

    它比split(“”)和join()快很多。为了进行比较,最好将数组打包成字符串,这样就不必比较数组。

        2
  •  5
  •   Robert Simmons    17 年前

    我也不是一个喜欢Ruby的人,但正如我在另一条评论中所指出的,这似乎适用于所描述的算法。

    s = "mississippi"
    s.split('').sort.join.gsub(/(.)\1{2,}/) { |s| s.length.to_s + s[0,1] } 
    

    当然,您需要确保单词是小写的,不包含数字等。

    我认为拆分/排序/连接部分非常简单。对我来说,有趣的部分是从打电话给gsub开始的。这将用后面块的返回值替换与正则表达式匹配的子字符串。reg ex查找任何字符并创建反向引用。这就是“()”部分。然后,我们使用反向引用“\1”继续匹配过程,该反向引用的计算结果为匹配的第一部分找到的任何字符。我们希望在总共最少出现三次的情况下,至少再找到该字符两次。这是使用量词“{2,}”完成的。

    如果这让人困惑,我道歉。通常情况下,对我来说,将解决方案形象化比清楚地解释它更容易。

        3
  •  2
  •   Norman Ramsey    17 年前

    split 消息将字符放入数组中,但一旦您对列表进行了排序,我就看不到一个很好的线性时间连接原语来返回字符串。我很惊讶。

    顺便提一句 . 在我认为值得考虑之前,我必须看到一些令人印象深刻的测量结果。如果避免运行长度编码,则可以 将任何字符串重新语法化 ,而不仅仅是一串字母。如果你知道你只有字母,并试图节省空间,你可以把它们5位打包成一个字母。


    编辑 join 我错过了。美好的