我有一个问题..附加

I have a issue.. Appending

我有这个代码:

  1 #!/local/usr/bin/ruby
  2 
  3 users = (1..255).to_a
  4 
  5 x = " "
  6 y = " "
  7 z = " "
  8 #a = " "
  9 
 10 count = 1
 11 users.each do |i|
 12   x << i if count == 1
 13   y << i if count == 2
 14   z << i if count == 3
 15  # if x.length == 60
 16  #   a << i if count == 1
 17  #   a << i if count == 2
 18  #   a << i if count == 3
 19  # else
 20  # end
 21   if count == 3
 22     count = 1
 23   else
 24     count += 1
 25   end
 26 end
 27 
 28 puts x.length
 29 puts y.length
 30 puts z.length
 31 #puts a.length
 32 

这段代码的作用是将数字 1-255 附加到三个不同的字符串中,并输出每个字符串中有多少个数字。

有效

工作代码示例:

[user@server ruby]$ ruby loadtest.rb
86
86
86
[user@server ruby]$ 

现在我想要它做的是有一个名为 a 的故障保护,如上所示,注释掉,我想要的是这个,如果每个字符串包含 60 个数字,我希望它附加到 a 字符串,直到没有数字为止。

当我尝试使用注释掉的部分执行此操作时,它会输出:

[user@server ruby]$ ruby loadtest.rb
86
86
86
4
[user@server ruby]$ ruby loadtest.rb

为什么?!我做错了什么?

... if each string contains 60 numbers I want it to append into the a string until there are no more numbers

正如所写,即使在达到您的限制后,您也无条件追加到 x、y、z。 您需要围绕此代码添加一个条件:

   x << i if count == 1
   y << i if count == 2
   z << i if count == 3

以便它在达到您的限制后停止追加。

从不执行任何操作的 else 块的外观来看,我认为您正朝那个方向前进:

  if x.length == 60
    a << i if count == 1
    a << i if count == 2
    a << i if count == 3
  else
   x << i if count == 1
   y << i if count == 2
   z << i if count == 3
  end

即便如此,也不会完全按照您的要求进行。 您需要检查要追加的字符串,看看它是否已达到限制。

我建议重构以使其更简洁:

 users.each do |i|
   target_string = case count
   when 1 then x
   when 2 then y
   when 3 then z
   end

   target_string = a if target_string.length == 60

   target_string << i

   if count == 3
     count = 1
   else
     count += 1
   end
 end

在将数字压入这些变量时,使用数组而不是字符串可能更好。

让我提出一个解决方案,它或多或少地实现了您想要做的事情,但使用了一些将来可能有用的 Ruby 技巧。

x, y, z = r = Array.new(3) {[]}
a = []

iter = [0,1,2].cycle

(1..255).each do |i|
  r.all? {|i| i.size == 60} ? a << i : r[iter.next] << i
end

p x.size, y.size, z.size
p a.size

让我们定义数组。即使我有数组 xyz,它们之所以存在只是因为它们存在于您的代码中 - 我认为我们只需要三个数组,每个数组都会收集数字因为它们是从 1 到 255 之间的一系列数字中一个接一个地挑选出来的。 x,y,z = r 使用并行赋值技术,等同于 x,y,z = r[0],r[1],r[2]。此外,使用 Array.new(3) {[]} 有助于创建 Array of Array,这样当我们访问 r[1] 时,它默认使用空数组 ([]) 进行初始化。

x, y, z = r = Array.new(3) {[]}
a = []

为了确定从范围中选取的下一个数字必须放在哪个数组中,我们将使用从 Enumerable#cycle 生成的枚举器。这个枚举器很特别——因为它本质上是软的或无限的——我们可以通过调用 next 不断要求它给出一个元素,它会循环遍历 [0,1,2] 的数组元素——返回我们 0,1,2,0,1,2,0,1,2...无限。

iter = [0,1,2].cycle

接下来,我们将遍历数字范围 1..255。在每次迭代期间,我们将在 Enumerable#all? 的帮助下检查我们正在收集数字的所有 3 个数组是否都具有所需的 60 大小 - 如果是,我们会将数字附加到数组 a - 否则我们将根据 iter 枚举器返回的数组索引将其分配给 r 的子数组之一。

(1..255).each do |i|
  r.all? {|i| i.size == 60} ? a << i : r[iter.next] << i
end

最后,我们打印每个数组的大小。

p x.size, y.size, z.size
#=> 60, 60, 60
p a.size
#=> 75

What this code does is append The numbers 1-255 into three different strings and outputs how many numbers are in each string.

为了便于阅读而减少迭代值的数量后,这是它正在做的事情:

users = (1..5).to_a

x = " "
y = " "
z = " "

count = 1
users.each do |i|
  x << i if count == 1 # => " \u0001", nil, nil, " \u0001\u0004", nil
  y << i if count == 2 # => nil, " \u0002", nil, nil, " \u0002\u0005"
  z << i if count == 3 # => nil, nil, " \u0003", nil, nil

  if count == 3
    count = 1
  else
    count += 1
  end
end

x # => " \u0001\u0004"
y # => " \u0002\u0005"
z # => " \u0003"

puts x.length
puts y.length
puts z.length

# >> 3
# >> 3
# >> 2

您的代码在字符串中创建二进制文件,而不是我们通常认为的 "numbers" 数字。

继续,您可以使用 each_with_indexcase/when 清理您的逻辑。为了使结果更具可读性,我将累积字符串转换为数组:

users = (1..5).to_a

x = []
y = []
z = []

users.each_with_index do |i, count|
  case count % 3
  when 0
    x << i
  when 1
    y << i
  when 2
    z << i
  end
end

x # => [1, 4]
y # => [2, 5]
z # => [3]

puts x.length
puts y.length
puts z.length

# >> 2
# >> 2
# >> 1

真正的技巧是使用 %,它对值取模。