使用哈希问题中的关键字切换字符串中的单词

Switching words in string with keywords from hash problem

我正在尝试创建一种方法来将字符串中的单词与散列中的关键字进行切换。例如,有字符串:

my_string = "France france USA usa ENGLAND england ENGland"

这是我的哈希:

my_hash = {"england" => "https://google.com"}

还有一个循环:

occurrences = {}
my_string.gsub!(/\w+/) do |match|
  key = my_hash[match.downcase]
  count = occurrences.store(key, occurrences.fetch(key, 0).next)

  count > 2 ? match : "<a href = #{key}>#{match}</a>"
end

这个循环的输出是:

 <a href = >France</a> <a href = >france</a> USA usa <a href = https://google.com>ENGLAND</a> <a href = https://google.com>england</a> ENGland

预期输出:

France france USA usa <a href = https://google.com>ENGLAND</a> <a href = https://google.com>england</a> ENGland

你在这里看到的问题是我的循环总是接管字符串中前两个单词的 <a href> 标记,无论它们是否在哈希中(正如你在 [=30 中看到的那样) =] 示例)并且它应该像 'England' 示例中那样工作(前两个 'Englands' 成为超链接但不是第三个,因为它应该工作)。

P.S - 附加问题:有什么方法可以避免字符串中已经存在的超链接而不去碰它们?例如 - 如果字符串中已经有一个 'England' 超链接但带有另一个 href.

我不是 100% 清楚你的问题所需的输出是什么,但如果你只想替换与哈希中的键匹配的单词,只需添加一个 if (或 next) 在你的哈希查找之后。此外,变量 key 用于存储查找到的 value,因此我将其重命名并递增 key 而不是 occurrences 哈希中的 value。这似乎更符合你的要求。

occurrences = {}
my_string.gsub!(/\w+/) do |match|
  key = match.downcase
  value = my_hash[key]
  next match unless value

  count = occurrences.store(key, occurrences.fetch(key, 0).next)

  count > 2 ? match : "<a href = #{value}>#{match}</a>"
end
my_string = "France france USA usa ENGLAND england ENGland"
my_hash = {"england"=>"https://google.com"}
my_string.split
         .chunk(&:downcase)
         .flat_map do |country,a|
            a.flat_map.with_index do |s,i|
              if i < 2 && my_hash.key?(country)    
                "<a href = #{my_hash[country]}>#{s}</a>"
              else
                s    
              end
            end
          end.join(' ')
  #=> "France france USA usa <a href = https://google.com>ENGLAND</a> <a href = https://google.com>england</a> ENGland"

Enumerable#chunk and Enumerable#flat_map

注意

enum0 = my_string.split.chunk(&:downcase)
  #=> #<Enumerator: #<Enumerator::Generator:0x00007ff90c13bc28>:each>

这个枚举器生成的值可以通过将其转换为数组来查看。

enum0.to_a
  #=> [["france", ["France", "france"]], ["usa", ["USA", "usa"]],
  #    ["england", ["ENGLAND", "england", "ENGland"]]]

然后

enum1 = enum0.flat_map
  #=> #<Enumerator: #<Enumerator: #<Enumerator::Generator:0x00007ff90c113e58>:each>:flat_map>

enum1生成并赋值给两个block变量的初始值如下

country, a = enum1.next
  #=> ["france", ["France", "france"]] 
country
  #=> "france"
a #=> ["France", "france"]