ruby - 如何从字符串数组中生成可能的字母顺序组合?
Posted
技术标签:
【中文标题】ruby - 如何从字符串数组中生成可能的字母顺序组合?【英文标题】:ruby - how to generate the possible sequential combination of letters from an array of strings? 【发布时间】:2014-04-21 04:07:57 【问题描述】:我有一个字符串数组:
["ABC", "GHI"]
我想要所有的“字母”组合,从左到右读取,即
["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"
【问题讨论】:
不清楚你指定的数组遵循什么规则。此外,您写了您想要的组合,但这似乎与您想要"AG"
而不是"GA"
相矛盾。问题不清楚。
顺序组合请:)
@sawa 有道理。也不清楚是什么决定了组合的长度。你只想组合字符串数组的长度吗?
【参考方案1】:
这是你需要的:
a = ["ABC","DEF", "GHI"]
a.map(&:chars).reduce(&:product).map(&:join)
顺便说一句,您在示例输出中犯了一些错误,根据您的规范,不应该有以 E 或 F 开头的字符串。所以我想你的意思不是"ECH", "ECI", "FCG", "FCH", "FCI"
,而是"CEH", "CEI", "CFG", "CFH", "CFI"
。
编辑:
chars
返回一个枚举器,而不是一个数组,并且在 2.0 之前的 Ruby 版本中,它们没有 product
方法。因此,在这些版本中,只需像这样使用to_a
:
a.map(&:chars).map(&:to_a).reduce(&:product).map(&:join)
【讨论】:
在这种情况下,为什么要使用flat_map
而不是简单的map
?
这是一个错误,同时将其编辑掉。实际上flat_map
也可以,只是不需要。
好的,很酷。我很好奇并了解了 :product
和 :flat_map
做了什么。没想到我能做到。干杯!
这行得通,但我认为应该有更有效的方法。
效率如何?这是一个易于阅读、易于理解的短代码行,程序员只需 5 秒即可编写完成。除了所需的输出之外,您从未在问题中陈述过任何其他内容。请接受我的回答,因为这确实有效,如果您有特定需求,请提交一份新的。【参考方案2】:
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
【讨论】:
我刚开始写这样的东西.. 为什么不用#split
?
@ArupRakshit 你的意思是代替each_char
?这是一种更间接的方式。
@sawa 那么s.scan(/./)
会怎么样?如果它工作,那么你不需要输入 - s.each_char.to_a
.. :-)
@ArupRakshit 我不是在打代码高尔夫。我优先考虑概念的简单性,而不是减少我必须输入的字符数。
顺便说一句,在我的基准测试中使用 map(&:chars)
比 map |s| s.each_char.to_a
快约 10%。【参考方案3】:
递归解决方案:
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"]
【讨论】:
我认为您的意思是“非破坏性”。 (当然,因为map
是非破坏性的,所以不需要dup
:)
)
-2 为我,安德鲁,但为您 -1,因为第一次没有看到。
你给自己-1 ..你太大胆了.. :p
+1 看起来不错,虽然我尝试了一个长字并得到了doit(["MUMMIFICATION"]) SystemStackError: stack level too deep
以上是关于ruby - 如何从字符串数组中生成可能的字母顺序组合?的主要内容,如果未能解决你的问题,请参考以下文章