【问题标题】:Ruby string substitution with multiple options具有多个选项的 Ruby 字符串替换
【发布时间】:2017-07-29 21:09:05
【问题描述】:

我想做字符串替换。使用 gsubtr 我可以提供单个输入字符并将其映射到单个输出值,但我想基于多个映射创建多个输出字符串:

swap = { 
  'a' => ['$', '%', '^'],
  'b' => ['3'],
  'c' => ['4', '@'],
}

对于输入字符串'abc',我应该得到以下输出字符串:

  • '$34'
  • '$3@'
  • '%34'
  • '%3@'
  • '^34'
  • '^3@'

对于任意数量的输入和映射,是否有一种简单的方法可以做到这一点?实际上,它可能是大约 10 个输入和最多 3 个映射,通常只有一个。

【问题讨论】:

  • 它就像拥有三个嵌套循环(枚举所有组合)一样简单(在这种情况下),并且在最里面的循环中调用 tr/gsub。
  • 我承认,尽管至少进行通用实现并非易事。不过试试看吧。
  • Robin,感谢您选择我的答案,但您确实应该等待一段时间(也许 2 多个小时),然后再授予绿党。快速选择可能会阻止其他答案,并且,对于仍在研究答案的其他人来说,这是不礼貌的。不用着急。请考虑删除复选标记并稍后再决定。

标签: ruby string-substitution


【解决方案1】:
def gen_products(swap, str)
  swap_all = Hash.new { |_,k| [k] }.merge(swap) 
  arr = swap_all.values_at(*str.chars)
  arr.shift.product(*arr).map(&:join)
end

请参阅Hash::new(带有块)、Hash#values_atArray#product。如果h = Hash.new { |_,k| [k] }h 没有密钥k,则h[k] 返回[k]

swap = { 'a'=>['$', '%', '^'], 'b'=>['3'], 'c'=>['4', '@'] }

gen_products(swap, "abc")
  #=> ["$34", "$3@", "%34", "%3@", "^34", "^3@"]

这里

swap_all = Hash.new { |_,k| [k] }.merge(swap) 
  #=> {"a"=>["$", "%", "^"], "b"=>["3"], "c"=>["4", "@"]}
vals = swap_all.values_at(*str.chars)
  #=> [["$", "%", "^"], ["3"], ["4", "@"]]

另一个例子:

gen_products(swap, "bca")
  #=> ["34$", "34%", "34^", "3@$", "3@%", "3@^"]

还有一个:

gen_products(swap, "axbycx")
  #=> ["$x3y4x", "$x3y@x", "%x3y4x", "%x3y@x", "^x3y4x", "^x3y@x"]

这里

swap_all = Hash.new { |_,k| [k] }.merge(swap)
  #=> {"a"=>["$", "%", "^"], "b"=>["3"], "c"=>["4", "@"]}
vals = swap_all.values_at(*str.chars)
  #=> [["$", "%", "^"], ["x"], ["3"], ["y"], ["4", "@"], ["x"]]

【讨论】:

  • 哦,这很聪明 :) 忘了.product。递归地重新实现它。这看起来不那么性感。
  • 您可以在分配期间通过first, *others = swap.values_at(*str.chars) 分解数组,以便将方法的第二行缩短为first.product(*others)
  • @Stefan,另一种(不太理想,imo)方式是arr = swap.values_at(*str.chars); arr.shift.product(*arr)
  • 刚刚意识到,如果 str 中有不在交换数组中的字符,这将失败,即你这样称呼它:gen_products(swap, "abcxyz") 是一个简单的修复吗?
  • 我想在所有交换结束时留下 xyz。
猜你喜欢
  • 2011-12-29
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-04
  • 2020-08-31
  • 2015-03-15
  • 1970-01-01
相关资源
最近更新 更多