ruby – 如何从字符串数组生成可能的顺序字母组合?

我有一个字符串数组:

["ABC", "GHI"] 

ad我想要所有’字母’组合,从左到右读取,即

 ["AG", "AH", "AI", "BG", "BH", "BI", "CG", "CH", "CI"] 

但不是

 "GA", "GB", "HA", etc. 

同样的,

 ["ABC", "DEF", "GHI"] 

应该生成

 ["ADG", "ADH", "ADI", "AEG", "AEH", "AEI", "AFG", "AFH", "AFI", "BDG", "BDH", "BDI", "BEG", "BEH", "BEI", "BFG", "BFH", "BFI", "CDG", "CDH", "CDI", "CEG", "CEH", "CEI", "CFG", "CFH" "CFI"] 

但不是

 "DAG", "GAD" or "GFA" 

这就是你需要的:

 a = ["ABC","DEF", "GHI"] a.map(&:chars).reduce(&:product).map(&:join) 

顺便说一句,你在示例输出中出现了一些错误,根据你的规范,永远不应该有以E或F开头的字符串。 所以我想而不是"ECH", "ECI", "FCG", "FCH", "FCI" ,而不是"CEH", "CEI", "CFG", "CFH", "CFI"

编辑:

chars返回一个Enumerator,而不是一个数组,而在2.0之前的Ruby版本中,它们没有product方法。 所以在这些版本中,只需像这样使用to_a

 a.map(&:chars).map(&:to_a).reduce(&:product).map(&:join) 
 a = ["ABC","DEF", "GHI"] first, *rest = a.map{|s| s.each_char.to_a} first.product(*rest).map(&:join) # => # ["ADG", "ADH", "ADI", "AEG", "AEH", "AEI", "AFG", "AFH", "AFI", "BDG", "BDH", "BDI", # "BEG", "BEH", "BEI", "BFG", "BFH", "BFI", "CDG", "CDH", "CDI", "CEG", "CEH", "CEI", # "CFG", "CFH", "CFI"] 

基准与@ ggPeti的解决方案相比:

 t = Time.now 50000.times do a.map(&:chars).reduce(&:product).map(&:join) end puts Time.now - t # => 2.037303374 t = Time.now 50000.times do first, *rest = a.map{|s| s.each_char.to_a} first.product(*rest).map(&:join) end puts Time.now - t # => 1.670047516 

递归解决方案:

 def doit(b) recurse(b.map(&:chars)) end def recurse(a) (a.size==2 ? a.first.product(a.last) :a.shift.product(recurse a)).map(&:join) end doit(["ABC", "DEF", "GHI"]) #=> ["ADG", "ADH", "ADI", "AEG", "AEH", "AEI", "AFG", "AFH", "AFI", # "BDG", "BDH", "BDI", "BEG", "BEH", "BEI", "BFG", "BFH", "BFI", # "CDG", "CDH", "CDI", "CEG", "CEH", "CEI", "CFG", "CFH", "CFI"] doit(["ABC", "DE", "FGHI"]) #=> ["ADF", "ADG", "ADH", "ADI", "AEF", "AEG", "AEH", "AEI", # "BDF", "BDG", "BDH", "BDI", "BEF", "BEG", "BEH", "BEI", # "CDF", "CDG", "CDH", "CDI", "CEF", "CEG", "CEH", "CEI"]