我正在尝试做类似字符串分析器的事情,我需要检索单词的结尾并将其与哈希键进行比较
word = "Test"
ending_hash = {"e" => 1, "st" => 2}
output = 2
在这种情况下,我需要输出为2,但实际上我不知道结尾的长度是1个字符还是2个字符。有可能吗?
答案 0 :(得分:2)
最初,假设您知道word
以(至少)个键ending_hash
结尾。然后,您可以编写:
word = "Test"
ending_hash = {"e" => 1, "st" => 2}
ending_hash.find { |k,v| word.end_with?(k) }.last
#=> 2
请参见Enumerable#find,String#end_with?和Array#last。
中间计算如下:
ending_hash.find { |k,v| word.end_with?(k) }
#=> ["st", 2]
如果不确定任何键是否与字符串的末尾匹配,请输入:
ending_hash = {"e" => 1, "f" => 2}
arr = ending_hash.find { |k,v| word.end_with?(k) }
#=> nil
arr.nil? ? nil : arr.last
#=> nil
或更好:
ending_hash.find { |k,v| word.end_with?(k) }&.last
#=> nil
&
是Safe Navigation Operator。简而言之,如果&
之前的表达式返回nil
,则SNO会立即为整个表达式返回nil
,而不执行last
。
即使word
必须以键之一结尾,您也可能希望以这种方式编写它,以便您可以检查返回值并在nil
处引发异常。
您也可以写:
ending_hash.find { |k,v| word.match? /#{k}\z/ }&.last
正则表达式为“匹配字符串末尾k
上#{k}
(\z
)的 value ”。 / p>
请注意以下几点:
{"t"=>1, "st"=>2}.find { |k,v| word.end_with?(k) }&.last
#=> 1
{"st"=>1, "t"=>2}.find { |k,v| word.end_with?(k) }&.last
#=> 1
所以键的顺序可能很重要。
最后,由于在块计算中未使用块变量v
,因此块变量通常会被写成|k,_|
或|k,_v|
,主要是向读者传达仅{ {1}}用于块计算。
答案 1 :(得分:0)
如果您知道结尾的 lengths 数量很少,那么检查所有可能的长度比检查所有结尾的速度要快得多。 (从最长到最短的位置检查它们也是有道理的,以防它们重叠,否则较短的将永远不会匹配。)
懒惰的一线客:
(-2..-1).lazy.map { |cut| ending_hash[word[cut..]] }.find(&:itself)
功能版本:
(-2..-1).inject(nil) { |a, e| a || ending_hash[word[e..]] }
钝但潮湿的版本:
ending_hash[word[-2..]] || ending_hash[word[-1..]]