如何将这个ruby字符串转换为普通数组?

时间:2015-01-06 19:55:01

标签: javascript ruby arrays

我正在检索一个如下所示的字符串:

"[[[256, 498]]] [[[256, 498]], []] [[[256, 498]], [], []] [[[256, 498]], [], [], []]"

我怎样才能让它看起来像这样?

[[256,498],[256,498],[],[256,498],[],[],[256,498],[],[],[]]

寻找ruby或JavaScript的解决方案。

2 个答案:

答案 0 :(得分:4)

仍在寻找更优雅的解决方案,但这将有效

str.scan(/\[+(\d*, ?\d*)?\]+/).flatten.map do |a|
  a ? a.split(",").map(&:to_i) : []
end
#=> [[256, 498], [256, 498], [], [256, 498], [], [], [256, 498], [], [], []]

方法论细分

scanned_string_array = str.scan(/\[+(\d*, ?\d*)?\]+/)
#=> [["256, 498"], ["256, 498"], [nil], ["256, 498"], [nil], [nil], ["256, 498"], [nil], [nil], [nil]]
scanned_string_array.flatten
#=> ["256, 498", "256, 498", nil, "256, 498", nil, nil, "256, 498", nil, nil, nil]
scanned_string_array.flatten.map do |a|
  #if a is nil return empty array otherwise split on comma and map to Integer
  a ? a.split(",").map(&:to_i) : []
end
#=> [[256, 498], [256, 498], [], [256, 498], [], [], [256, 498], [], [], []]

<强>更新

找到一种更优雅的方式或者至少我更喜欢它

str.scan(/\[+(\d*),?\s?(\d*)?\]+/).map do |a|
  a.reject(&:empty?).map(&:to_i)
end
#=> [[256, 498], [256, 498], [], [256, 498], [], [], [256, 498], [], [], []]

答案 1 :(得分:1)

我会按如下方式提取数组。

<强>代码

def extract(str)
  str.scan(/\[[^\[\]]*\]/).map { |s| s.scan(/\d+/).map(&:to_i) }
end

示例

str = "[[[256, 498]]] [[[256, 498]], []] [[[256, 498]], " \
      "[], []] [[[256, 498]], [], [], []]"
extract(str)
  #=> [[256, 498], [256, 498], [], [256, 498], [], [], [256, 498], [], [], []] 

<强>解释

对于上面的例子:

str.scan提取"[...]"形式的所有字符串,其中...是开头和右括号以外的字符:

a = str.scan(/\[[^\[\]]*\]/)
  #=> ["[256, 498]", "[256, 498]", "[]", "[256, 498]",
  #    "[]", "[]", "[256, 498]", "[]", "[]", "[]"]

map然后将a的每个元素传递给它的块,并将该值赋给块变量s,第一个是:

s = "[256, 498]"

然后执行以下操作:

ss = s.scan(/\d+/) #=> ["256", "498"] 
ss.map(&:to_i)     #=> [256, 498] 

"[]"传递到块中时:

s = "[]"
ss = s.scan(/\d+/) #=> []
ss.map(&:to_i)     #=> []

<强>基准

我已经要求对方法进行基准比较。我很高兴能够满足这一要求,并在下面报告结果。唉,我的解决方案并没有那么好,但是当基准的请求来自某个名字不包含元音的工程师时,似乎总会发生这种情况(除了&#34;有时是y&#34;)。

我刚刚进行了一次基准测试,但是当我改变测试数据时结果相似。

方法比较

module Methods
  def smnky1(str)
    str.scan(/\[+(\d*, ?\d*)?\]+/).flatten.map do |a|
      a ? a.split(",").map(&:to_i) : []
    end
  end

  def smnky2(str)
    str.scan(/\[+(\d*),?\s?(\d*)?\]+/).map do |a|
      a.reject(&:empty?).map(&:to_i)
    end
  end

  def cary(str)
    str.scan(/\[[^\[\]]*\]/).map { |s| s.scan(/\d+/).map(&:to_i) }
  end
end

@methods = Methods.instance_methods(false)
include Methods
def compute(m, str) send(m, str) end

基准代码

require 'benchmark'

@indent = @methods.map { |m| m.to_s.size }.max

def test(str, reps)
  exit if answers_not_all_the_same(str)
  Benchmark.bm(@indent) do |bm|
    @methods.each do |m|
      bm.report m.to_s do
        reps.times { compute(m, str) }
      end
    end
  end
end

def answers_not_all_the_same(str)
  same = @methods.map { |m| compute(m, str) }.uniq.size > 1
  puts same ? "all don't match" : "all match"
end

<强>结果

str = "[[[256, 498]]] [[[256, 498]], []] [[[256, 498]], " \
      "[], []] [[[256, 498]], [], [], []]"
reps = 100_000
puts "Example string, #{reps} repetitions"
test(str, reps)

Example string, 100000 repetitions
all match
             user     system      total        real
smnky1   1.830000   0.000000   1.830000 (  1.830457)
smnky2   1.920000   0.010000   1.930000 (  1.920094)
cary     2.750000   0.000000   2.750000 (  2.752946)