【问题标题】:Multiply all even indexed integers by two将所有偶数索引整数乘以 2
【发布时间】:2015-04-26 05:47:06
【问题描述】:

想要获取一个固定的整数并将所有偶数(索引)整数乘以 2。我认为最好的方法是首先将 fixnum 转换为数组。所以让我们说以下 16 位数:a = 4408041234567901

我知道我可以:

a.to_s.split('')

这会将“a”返回到“字符串”数字数组。但后来我无法跟进:

a.map!.with_index {|i,n| i.even? n*2}

我猜我有点纠结于如何创建一个方法来做到这一点。所以我的问题甚至可能是如何将这组数字变成一个固定数字/整数数组而不是字符串。

【问题讨论】:

  • 听起来你想将整数的偶数索引数字乘以 2。没有“整数的固定数”之类的东西。整数有数字,而不是其他整数。

标签: ruby arrays loops fixnum


【解决方案1】:

我希望通过创建一个包含要乘以的系数的Enumerator 来完全从循环中删除条件(偶数索引为 2,奇数索引为 1。)

coef = [2, 1].cycle

这实质上创建了一个Enumerator,当调用next 时,它交替返回21。然后,您可以使用它来将您的 map 简化为:

a.to_s.each_char.map { |v| v.to_i * coef.next }

【讨论】:

  • 真的很喜欢这个答案。谢谢。
【解决方案2】:

要将其更改为数组,您可以这样做

a = 4408041234567901
arr = a.to_s.chars.map(&:to_i)
# => [4, 4, 0, 8, 0, 4, 1, 2, 3, 4, 5, 6, 7, 9, 0, 1]

您还可以将备用数字乘以 2

arr = a.to_s.chars.map.with_index {|n,i| i.even? ? n.to_i * 2 : n.to_i }
# => [8, 4, 0, 8, 0, 4, 2, 2, 6, 4, 10, 6, 14, 9, 0, 1]

稍微改进一下,可以使用Hash来查找要相乘的数字。

h = {true => 2, false => 1}
a.to_s.each_char.map.with_index {|n,i| n.to_i * h[i.even?]}

编辑

我可以解释每个步骤,但是如果您自己尝试弄清楚会更好。打开 irb,输入a.to_s 并检查输出。然后输入a.to_s.chars 并检查输出等等..

【讨论】:

  • 您能否准确解释一下从将“a”转换为字符串、然后使用字符、然后“映射”它的过程?我是个新人,想确保我完全理解,而不是照搬过去,你知道吗?
【解决方案3】:
a = 4408041234567901

even_odd = [:even, :odd].cycle
   #=> #<Enumerator: [:even, :odd]:cycle> 

如果索引从最高位(最左边)的数字开始:

a.to_s.each_char.map { |d|
  (even_odd.next == :even) ? 2*d.to_i : d.to_i }
  #=> [8, 4, 0, 8, 0, 4, 2, 2, 6, 4, 10, 6, 14, 9, 0, 1]

如果索引以个位开头:

s = a.to_s
even_odd.next if s.size.even?
s.each_char.map { |d| ( even_odd.next == :even) ? 2*d.to_i : d.to_i }
  #=> [4, 8, 0, 16, 0, 8, 1, 4, 3, 8, 5, 12, 7, 18, 0, 2] 

以下是从零开始的索引从最高位开始的示例的步骤。

Array#cycle 将数组[:even, :odd] 转换为枚举数:

even_odd = [:even, :odd].cycle
even_odd.next #=> :even
even_odd.next #=> :odd
even_odd.next #=> :even
even_odd.next #=> :odd
...

b = a.to_s
  #=> "4408041234567901" 
enum0 = b.each_char
  #=> #<Enumerator: "4408041234567901":each_char> 

枚举器enum0b 的数字传递给map。我本来可以写:

b = a.to_s.chars
  # => ["4", "4", "0", "8", "0", "4", "1", "2",
  #     "3", "4", "5", "6", "7", "9", "0", "1"] 

但这会创建一个中间数组。枚举器没有,因此效率更高。继续...

enum1 = enum0.map     
  #=> #<Enumerator: #<Enumerator: "4408041234567901":each_char>:map> 

您可以将其视为“复合枚举器”。我们可以通过将其转换为数组来查看其内容:

enum1.to_a
  #=> ["4", "4", "0", "8", "0", "4", "1", "2",
  #    "3", "4", "5", "6", "7", "9", "0", "1"] 

each 方法会将枚举数的每个元素传递到块中。证明:

enum1.each { |d| (enum.next == :even) ? 2*d.to_i : d.to_i }
  # => [8, 4, 0, 8, 0, 4, 2, 2, 6, 4, 10, 6, 14, 9, 0, 1]

我们可以使用Enumerator#next 手动单步遍历enum1 的元素。我们将值赋给块变量d,并在块中执行计算以映射数字d

d = enum1.next
  #=> "4" 
(enum.next == :even) ? 2*d.to_i : d.to_i
  #=> (:even == :even) ? 2*"4".to_i : "4".to_i
  #=> (true) ? 8 : 4
  #=> 8 ("4" is mapped to 8)

d = enum1.next
  #=> "4" 
(enum.next == :even) ? 2*d.to_i : d.to_i
  #=> (:odd == :even) ? 2*"4".to_i : "4".to_i
  #=> (false) ? 8 : 4
  #=> 4 ("4" is mapped to 4)

d = enum1.next
  #=> "0" 
  #=> (:even == :even) ? 2*"0".to_i : "0".to_i
  #=> (true) ? 0 : 0
  #=> 8 ("0" is mapped to 0)

等等。

【讨论】:

  • 这对我来说似乎有点陌生。我不确定你为什么使用反向,我需要研究你在枚举上调用的下一个。不过还是谢谢你的回答!
  • 抱歉,reverse 是我所做的一些更改的产物。我展示了如何使用循环枚举器。我更喜欢使用 each_with_indexwith_index
猜你喜欢
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 2020-11-06
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 2014-01-29
  • 2013-10-09
相关资源
最近更新 更多