我想将任意字符串转换为字符串数组。最好用一个例子来解释转换。如果字符串是"8737928"
,我想返回以下数组。
#=> ["8737928",
# "8.737928", "87.37928", "873.7928", "8737.928", "87379.28", "873792.8",
# "8.7.37928", "8.73.7928", "8.737.928", "8.7379.28", "8.73792.8",
# "87.3.7928", "87.37.928", "87.379.28", "87.3792.8", "873.7.928",
# "873.79.28", "873.792.8", "8737.9.28", "8737.92.8", "87379.2.8",
# "8.7.3.7928", "8.7.37.928", "8.7.379.28", "8.7.3792.8", "8.73.7.928",
# "8.73.79.28", "8.73.792.8", "8.737.9.28", "8.737.92.8", "8.7379.2.8",
# "87.3.7.928", "87.3.79.28", "87.3.792.8", "87.37.9.28", "87.37.92.8",
# "87.379.2.8", "873.7.9.28", "873.7.92.8", "873.79.2.8", "8737.9.2.8",
# "8.7.3.7.928", "8.7.3.79.28", "8.7.3.792.8", "8.7.37.9.28", "8.7.37.92.8",
# "8.7.379.2.8", "8.73.7.9.28", "8.73.7.92.8", "8.73.79.2.8", "8.737.9.2.8",
# "87.3.7.9.28", "87.3.7.92.8", "87.3.79.2.8", "87.37.9.2.8", "873.7.9.2.8",
# "8.7.3.7.9.28", "8.7.3.7.92.8", "8.7.3.79.2.8", "8.7.37.9.2.8",
# "8.73.7.9.2.8", "87.3.7.9.2.8",
# "8.7.3.7.9.2.8"]
如您所见,在1到6之间的每个索引组合中,在字符串中插入0到6("8737928".size-1 #=> 6
)之间的小数点。由于小数点可能跟随或不跟随每个字符。最后,该数组包含2**6 #=> 64
个元素。
我该怎么做?
答案 0 :(得分:3)
def doit(str)
indices = (1..str.size-1).to_a
indices.each_with_object([str]) { |ndots, combos|
indices.combination(ndots).each { |sub| combos << dotify(str, sub) } }
end
def dotify(str, indices)
indices.reverse.each_with_object(str.dup) { |i,s| s.insert(i,'.') }
end
doit("8737928").size
#=> 64
doit "8737928"
#=> ["8737928",
# "8.737928", "87.37928", "873.7928", "8737.928", "87379.28", "873792.8",
# "8.7.37928", "8.73.7928", "8.737.928", "8.7379.28", "8.73792.8",
# "87.3.7928", "87.37.928", "87.379.28", "87.3792.8", "873.7.928",
# "873.79.28", "873.792.8", "8737.9.28", "8737.92.8", "87379.2.8",
# "8.7.3.7928", "8.7.37.928", "8.7.379.28", "8.7.3792.8", "8.73.7.928",
# "8.73.79.28", "8.73.792.8", "8.737.9.28", "8.737.92.8", "8.7379.2.8",
# "87.3.7.928", "87.3.79.28", "87.3.792.8", "87.37.9.28", "87.37.92.8",
# "87.379.2.8", "873.7.9.28", "873.7.92.8", "873.79.2.8", "8737.9.2.8",
# "8.7.3.7.928", "8.7.3.79.28", "8.7.3.792.8", "8.7.37.9.28", "8.7.37.92.8",
# "8.7.379.2.8", "8.73.7.9.28", "8.73.7.92.8", "8.73.79.2.8", "8.737.9.2.8",
# "87.3.7.9.28", "87.3.7.92.8", "87.3.79.2.8", "87.37.9.2.8", "873.7.9.2.8",
# "8.7.3.7.9.28", "8.7.3.7.92.8", "8.7.3.79.2.8", "8.7.37.9.2.8",
# "8.73.7.9.2.8", "87.3.7.9.2.8",
# "8.7.3.7.9.2.8"]
注意:
dotify("8737928", [1,3,5])
#=> "8.73.79.28"
答案 1 :(得分:2)
经过进一步的反思(见原文,下面可能是不正确的解决方案),看起来OP真正想做的是在字符串中每个可能的位置组合插入点。这是一个字面意思的方法:
def splits(str, prefix="")
c = str.size - 1
(0..c).flat_map do |m|
(0...c).to_a.combination(m).map do |n|
n.each_with_object(str.dup) {|i,s| s.insert(c-i, ?.) }
end
end
end
puts splits("8737928")
# => 8737928
# 873792.8
# 87379.28
# 87379.2.8
# 8737.928
# 8737.92.8
# 8737.9.28
# 8737.9.2.8
# 873.7928
# 873.792.8
# 873.79.28
# 873.79.2.8
# 873.7.928
# 873.7.92.8
# 873.7.9.28
# 873.7.9.2.8
# 87.37928
# 87.3792.8
# 87.379.28
# 87.379.2.8
# 87.37.928
# 87.37.92.8
# 87.37.9.28
# 87.37.9.2.8
# 87.3.7928
# 87.3.792.8
# 87.3.79.28
# 87.3.79.2.8
# 87.3.7.928
# 87.3.7.92.8
# 87.3.7.9.28
# 87.3.7.9.2.8
# 8.737928
# 8.73792.8
# 8.7379.28
# 8.7379.2.8
# 8.737.928
# 8.737.92.8
# 8.737.9.28
# 8.737.9.2.8
# 8.73.7928
# 8.73.792.8
# 8.73.79.28
# 8.73.79.2.8
# 8.73.7.928
# 8.73.7.92.8
# 8.73.7.9.28
# 8.73.7.9.2.8
# 8.7.37928
# 8.7.3792.8
# 8.7.379.28
# 8.7.379.2.8
# 8.7.37.928
# 8.7.37.92.8
# 8.7.37.9.28
# 8.7.37.9.2.8
# 8.7.3.7928
# 8.7.3.792.8
# 8.7.3.79.28
# 8.7.3.79.2.8
# 8.7.3.7.928
# 8.7.3.7.92.8
# 8.7.3.7.9.28
# 8.7.3.7.9.2.8
然而,尽管@ EliSadoff的解决方案并未一概而论,但我确实喜欢他的“想法,即一个时期可能是一个布尔决定。”如果我们考虑字符串中的位置,我们可以在其中插入一个句点作为二进制数 m 中的位,其长度与字符串相同(基数2)相同,我们可以简单地从0开始迭代到2 ( c -1) -1(其中 c 是字符串的长度)来获得每个可能的这样的数字。例如,如果我们的字符串是"abcd"
( c = 4),那么我们可以从0迭代到7(2 (4-1) -1)找到每个时期的位置:
m₁₀ | m₂ 4 2 1 | 4 2 1 | result
─────┼────┴─┴─┴─┼───┴───┴───┴───┼─────────
0 │ 0 0 0 │ a b c d │ abcd
1 │ 0 0 1 │ a b c • d | abc.d
2 │ 0 1 0 │ a b • c d | ab.cd
3 │ 0 1 1 │ a b • c • d | ab.c.d
4 │ 1 0 0 │ a • b c d | a.bcd
5 │ 1 0 1 │ a • b c • d | a.bc.d
6 │ 1 1 0 │ a • b • c d | a.b.cd
7 │ 1 1 1 │ a • b • c • d | a.b.c.d
唯一缺失的部分是根据第二列中的位插入句点。这很简单:为了确定我们是否需要在 n 位置插入一个句点,我们测试 m 中的 n 位是否为1为此,我们可以使用按位运算 m &amp; (1« n )。
将所有内容放在一起,我们得到以下内容:
def splits2(str)
c = str.size - 1
(0...2**c).map do |m|
0.upto(c).with_object(str.dup) do |i,s|
s.insert(c-i, ?.) if m & (1 << i) > 0
end
end
end
只是为了好玩,这是另一个也采用二进制数方法的解决方案,但方式不同。我将把它作为练习留给读者来弄清楚它是如何工作的:
def splits3(str)
c = str.size - 1
(0...2**c).map do |m|
dots = ("%*b" % [c,m]).each_char.map(&{?1=>?.})
str.each_char.zip(dots).join
end
end
与@ CarySwoveland的解决方案类似,但我认为有点简单:
def splits(str, pfx="")
return [] if str.empty?
(1...str.size).map {|i| pfx + str.dup.insert(i, ?.) } +
splits(str[1..-1], "#{pfx}#{str[0]}.")
end
p splits("8737928")
# => [ "8.737928", "87.37928", "873.7928", "8737.928", "87379.28", "873792.8",
# "8.7.37928", "8.73.7928", "8.737.928", "8.7379.28", "8.73792.8",
# "8.7.3.7928", "8.7.37.928", "8.7.379.28", "8.7.3792.8",
# "8.7.3.7.928", "8.7.3.79.28", "8.7.3.792.8",
# "8.7.3.7.9.28", "8.7.3.7.92.8",
# "8.7.3.7.9.2.8"
# ]
答案 2 :(得分:1)
要求不明确,我得出的结果与Cary和Jordan的结果不同:
def dot_it(prefix, suffix = nil)
return dot_it(prefix[0], prefix[1..-1]) if suffix.nil? # first call
(1...suffix.length).flat_map do |i|
sp, ss = "#{prefix}.#{suffix[0...i]}", suffix[i..-1]
["#{sp}.#{ss}", dot_it(sp, ss)].flatten.compact
end
end
dot_it("8737928")
#⇒ ["8.7.37928", "8.7.3.7928", "8.7.3.7.928", "8.7.3.7.9.28",
# "8.7.3.7.9.2.8", "8.7.3.7.92.8", "8.7.3.79.28", "8.7.3.79.2.8",
# "8.7.3.792.8", "8.7.37.928", "8.7.37.9.28", "8.7.37.9.2.8",
# "8.7.37.92.8", "8.7.379.28", "8.7.379.2.8", "8.7.3792.8",
# "8.73.7928", "8.73.7.928", "8.73.7.9.28", "8.73.7.9.2.8",
# "8.73.7.92.8", "8.73.79.28", "8.73.79.2.8", "8.73.792.8",
# "8.737.928", "8.737.9.28", "8.737.9.2.8", "8.737.92.8",
# "8.7379.28", "8.7379.2.8", "8.73792.8"]
我的方法给出:
dot_it("8737928").count
#⇒ 31
虽然上述两个答案都给出了21个结果。谁是对的?