【问题标题】:Parse a string without spaces into an array of individual words将没有空格的字符串解析为单个单词的数组
【发布时间】:2017-01-17 19:42:53
【问题描述】:

如果我有一个字符串“blueberrymuffinsareinsanelydelicious”,那么解析它的最有效方法是什么,这样我就剩下 [“blueberry”,“muffins”,“are”,“insanely”,“delicious”]?

我已经有了我的单词表(mac 的 /usr/share/dict/words),但是我如何确保完整的单词存储在我的数组中,又名:blueberry,而不是两个单独的单词,blue 和 berry。

【问题讨论】:

  • 您可以阅读您的单词列表,然后在搜索字符串之前按 word sizereverse order 对其进行排序。在这种情况下,如果您的单词列表是 ['blue','berry','blueberry'],它会变成 ['blueberry','berry','blue'],您的搜索将首先查找复合词。
  • 这听起来像XY Problem。你是怎么得到这份清单的?
  • 为什么解析blueberry而不是blueberry更好?这也不是一个有效的解决方案吗?
  • 我对这个问题投了反对票,因为不清楚需要什么,我认为任何数量的编辑都无济于事。这本质上是一个无法回答的问题。例如,应该如何拆分字符串"carrotate"["carrot", "ate"]? ["car", "rotate"]? ["car", "rot", "ate"]?。人们可以很容易地制作出具有数千种可能组合的更长的字符串。像这样的问题是在浪费每个人的时间,包括提问者的。
  • 如果字符串被分解成字典中的单词后,字符串中没有任何内容,我很确定这个问题是 NP 完全的。

标签: ruby string algorithm parsing


【解决方案1】:

虽然在某些情况下可能存在多种解释,而选择最佳解释可能会很麻烦,但您始终可以使用如下所示的相当幼稚的算法来处理它:

WORDS = %w[
  blueberry
  blue
  berry
  fin
  fins
  muffin
  muffins
  are
  insane
  insanely
  in
  delicious
  deli
  us
].sort_by do |word|
  [ -word.length, word ]
end

WORD_REGEXP = Regexp.union(*WORDS)

def best_fit(string)
  string.scan(WORD_REGEXP)
end

这将解析您的示例:

best_fit("blueberrymuffinsareinsanelydelicious")
# => ["blueberry", "muffins", "are", "insanely", "delicious"]

请注意,这会跳过所有不匹配的组件。

【讨论】:

  • 我认为从给定的起点保留所有可能的成功匹配是明智的。您可能会发现自己处于两个可能匹配项中较长的匹配项是错误的情况,甚至下一个词也不能完全消除结果的歧义。可能要等到几步之后才能解决歧义(如果有的话)。
  • @DerrellDurrett 从概念上讲这不是一个坏主意,但它确实使解决方案相当复杂。
  • 哈哈。是的。但这是实现回溯的唯一(明显)方法,因此如果您做出了错误的选择,您可以成功。否则你会在很多时候以失败告终。
  • @DerrellDurrett 正则表达式系统非常擅长导航以找到最长、最佳匹配,因此除了最极端的情况外,它在所有情况下都不是问题。
  • 正则表达式的使用非常有趣和巧妙。 :) 但是如果单词列表是一本大字典会发生什么?它会停滞不前,还是以其他方式失败?
【解决方案2】:

这是一种递归方法,它可以在我速度较慢的笔记本电脑上在 0.4 秒内找到正确的句子。

  • 它首先导入近 10 万个英文单词,并按大小递减排序
  • 对于每个word,它会检查text 是否以它开头
  • 如果是,它会从text 中删除word,将word 保留在一个数组中并递归调用自身。
  • 如果text为空,则表示找到了一个句子。
  • 它使用惰性数组在找到的第一个句子处停止。

text = "blueberrymuffinsareinsanelydeliciousbecausethey'rereallymoistandcolorful"

dictionary = File.readlines('/usr/share/dict/american-english')
                 .map(&:chomp)
                 .sort_by{ |w| -w.size }

def find_words(text, possible_words, sentence = [])
  return sentence if text.empty?
  possible_words.lazy.select{ |word|
    text.start_with?(word)
  }.map{ |word|
    find_words(text[word.size..-1], possible_words, sentence + [word])
  }.find(&:itself)
end

p find_words(text, dictionary)
#=> ["blueberry", "muffins", "are", "insanely", "delicious", "because", "they're", "really", "moist", "and", "colorful"]
p find_words('someword', %w(no way to find a combination))
#=> nil
p find_words('culdesac', %w(culd no way to find a combination cul de sac))
#=> ["cul", "de", "sac"]
p find_words("carrotate", dictionary)
#=> ["carrot", "ate"]

为了更快地查找,最好使用Trie

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 1970-01-01
    • 1970-01-01
    • 2017-10-22
    • 2022-07-29
    • 1970-01-01
    相关资源
    最近更新 更多