给定一组字符串,例如:
"Alice"
"Bob"
"C"
"Ca"
"Car"
"Carol"
"Caroling"
"Carousel"
并给出一个字符串,说:
"Carolers"
我想要一个返回数组内部最小前缀的函数。
对于上面的例子,函数应该返回:“Caro”。 (随后的电话将返回“Carole”)
我是Ruby的新手,虽然我可能会破解一些丑陋的东西(使用我的C / C ++ / Objective-C大脑),但我想学习如何正确(优雅地?)编写代码。
答案 0 :(得分:5)
Ruby中有一个名为Abbrev的神奇模块。
require 'abbrev'
abbreviations = Abbrev::abbrev([
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel"
])
carolers = Abbrev::abbrev(%w[Carolers])
(carolers.keys - abbreviations.keys).sort.first # => "Caro"
上面我拿了第一个元素,但这显示了还有什么可用。
pp (carolers.keys - abbreviations.keys).sort
# >> ["Caro", "Carole", "Caroler", "Carolers"]
在函数中包装所有上述内容,计算生成的缺失元素,然后迭代它们,将它们放到一个块中,或者使用枚举器逐个返回它们。
这是为单个单词生成的内容。对于数组来说,它更复杂。
require 'pp'
pp Abbrev::abbrev(['cat'])
# >> {"ca"=>"cat", "c"=>"cat", "cat"=>"cat"}
pp Abbrev::abbrev(['cat', 'car', 'cattle', 'carrier'])
# >> {"cattl"=>"cattle",
# >> "catt"=>"cattle",
# >> "cat"=>"cat",
# >> "carrie"=>"carrier",
# >> "carri"=>"carrier",
# >> "carr"=>"carrier",
# >> "car"=>"car",
# >> "cattle"=>"cattle",
# >> "carrier"=>"carrier"}
答案 1 :(得分:3)
您的问题仍然与您期望的结果不符。您似乎需要前缀,而不是子串(因为"a"
将是数组中尚未存在的最短子串)。要搜索前缀,这应该足够了:
array = [
"Alice",
"Bob",
"C",
"Ca",
"Car",
"Carol",
"Caroling",
"Carousel",
]
str = 'Carolers'
(0..str.length).map{|i|
str[0..i]
}.find{|s| !array.member?(s)}
答案 2 :(得分:0)
我不是Ruby专家,但我认为您可能希望通过将您的集转换为trie来解决此问题。一旦你构建了trie,你的问题就可以简单地从trie的根部向下走,沿着单词中所有字母的边缘,直到你找到一个没有标记为单词或走路的节点。脱掉了特里。在任何一种情况下,您都找到了一个不属于任何单词的节点,并且您所拥有的单词的最短前缀在该集合内部尚不存在。此外,这将允许您快速运行任意数量的前缀检查,因为在您构建了trie之后,算法在字符串的长度上花费的时间最多是线性的。
希望这有帮助!
答案 3 :(得分:0)
我不确定你要求的是什么,而不是一些Ruby代码的例子来找到公共前缀。我假设你想找到最小的字符串,它是给定集合中字符串数最多的前缀。这是一个示例实现:
class PrefixFinder
def initialize(words)
@words = Hash[*words.map{|x|[x,x]}.flatten]
end
def next_prefix
max=0; biggest=nil
@words.keys.sort.each do |word|
0.upto(word.size-1) do |len|
substr=word[0..len]; regex=Regexp.new("^" + substr)
next if @words[substr]
count = @words.keys.find_all {|x| x=~regex}.size
max, biggest = [count, substr] if count > max
#puts "OK: s=#{substr}, biggest=#{biggest.inspect}"
end
end
@words[biggest] = biggest if biggest
biggest
end
end
pf = PrefixFinder.new(%w(C Ca Car Carol Caroled Carolers))
pf.next_prefix # => "Caro"
pf.next_prefix # => "Carole"
pf.next_prefix # => "Caroler"
pf.next_prefix # => nil
没有评论此代码的性能(或正确性),但它确实显示了一些Ruby习语(实例变量,迭代,散列等)。
答案 4 :(得分:0)
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> y = Array.new
=> str="Carolers"
将给定的字符串拆分为数组
=> x=str.split('')
# ["C","a","r","o","l","e","r","s"]
形成所有组合
=> x.each_index {|i| y << x.take(i+1)}
# [["c"], ["c", "a"], ["c", "a", "r"], ["c", "a", "r", "o"], ["c", "a", "r", "o", "l"], ["c", "a", "r", "o", "l", "e"], ["c", "a", "r", "o", "l", "e", "r"], ["c", "a", "r", "o", "l", "e", "r", "s"]]
使用Join连接
=> y = y.map {|s| s.join }
# ["c", "ca", "car", "caro", "carol", "carole", "caroler", "carolers"]
从y中选择输入数组中不可用的第一项
=> y.select {|item| !inn.include? item}.first
您将获得&#34; caro&#34;
汇总所有
def FindFirstMissingItem(srcArray,strtocheck)
y=Array.new
x=strtocheck.split('')
x.each_index {|i| y << x.take(i+1)}
y=y.map {|s| s.join}
y.select {|item| !srcArray.include? item}.first
end
并致电
=> inn = ["Alice","Bob","C","Ca","Car","Carol","Caroling","Carousel"]
=> str="Carolers"
FindFirstMissingItem inn,str
答案 5 :(得分:0)
非常简单的版本(但不是非常Rubyish):
str = 'Carolers'
ar = %w(Alice Bob C Ca Car Carol Caroling Carousel)
substr = str[0, n=1]
substr = str[0, n+=1] while ar.include? substr
puts substr