【问题标题】:How to square an array of numbers in ruby with while without `each` `map` or `collect` methods?如何在没有`each``map`或`collect`方法的情况下用while对ruby中的数字数组进行平方?
【发布时间】:2020-01-17 21:25:02
【问题描述】:

我是 RUBY 编码的新手。我正在尝试编写一个方法,将数字数组中的每个元素平方并返回这些数字平方的新数组。尝试使用 while 循环而不使用 eachcollectmap。无法理解如何索引/循环数组和正方形的每个单独元素是 (**)。

这对我来说是有意义的,但我知道它是错误的。

def square_array(numbers)
  count = 0
  while count < numbers.length do
    numbers.index ** 2 
  end
  square_array(numbers)
end 

有人能帮帮我吗?谢谢!

【问题讨论】:

  • 如果您能解释一下the documentation,您确切地不清楚什么会很有帮助。这样,Ruby 开发人员可以改进文档,以便未来的开发人员不会遇到同样的问题。帮助世界变得更美好!
  • @JörgWMittag 祝你好运。 :)

标签: arrays ruby methods square


【解决方案1】:

不使用 each、map 或 collect。

def square_array(array)
 new_array = []
  array.length.times do |index|
  new_array.push(array[index] ** 2)
  end
 new_array
end

【讨论】:

    【解决方案2】:

    这是我的解决方案:

    def square_array(numbers)
      new_array = []
      counter = 0 
      while counter < numbers.length()
      new_array.push(numbers[counter] * numbers[counter])
      counter += 1
      end 
      return new_array
    end
    

    【讨论】:

      【解决方案3】:

      使用 for 循环?

      ary = [1,2,3]
      
      res = []
      for n in ary do
        res << n ** 2
      end
      
      res
      #=> [1, 4, 9]
      

      但最好还是坚持map

      【讨论】:

        【解决方案4】:
        def sq(arr)
          enum = arr.each
          a = []
          loop do
            n = enum.next
            a << n*n
          end
          a
        end
        

        sq [1, 2, 3, 4]
          #=> [1, 4, 9, 16]
        

        请参阅Array#eachKernel#loopEnumerator#next。可以使用Kernel#to_enum(记录在Object)代替Array#each

        【讨论】:

        • 有趣的方法,使用外部迭代器和loop,这样就不必增加和跟踪计数器。
        【解决方案5】:

        更实用的方法是使用递归。

        fun =
          ->(acc = [], arr, map, fun) {
            arr.empty? ? acc : fun.(acc << map.(arr.shift), arr, map, fun)
          }
        #⇒ #<Proc:0x000055ab64333fa0@(pry):12 (lambda)>
        

        对于任何映射器(例如平方根),都可以像这样使用它:

        fun.([1,2,3,4,5], ->(e) { e ** 2 }, fun)
        #⇒ [1, 4, 9, 16, 25]
        

        请注意!这种方法改变初始数组,因此在传递给函数之前应该明确地array.dup'ed。为了消除通过传递函数本身的必要性,我们需要一个包装器。

        fun =
          ->(acc = [], arr, map, fun) {
            arr.empty? ? acc : fun.(acc << map.(arr.shift), arr, map, fun)
          }
        #⇒ #<Proc:0x000055ab64333fa0@(pry):12 (lambda)>
        mapper = ->(arr, map) { fun.([], arr.dup, map, fun) }
        

        并像这样使用它:

        arr = [1,2,3,4,5]
        mapper.(arr, ->(e) { e ** 2 })
        #⇒ [1, 4, 9, 16, 25]
        arr
        #⇒ [1, 2, 3, 4, 5]
        

        【讨论】:

        • 如果它改变了原始数组,它如何“更实用”?副作用几乎是功能性的相反
        • @JörgWMittag 通过将这个函数包装在-&gt;(arr, map) { fun.([], arr.dup, map, fun)} 中,我可以消除bothfun 作为名称传递给 的必要性副作用,我在后文中清楚地说明了这一点。我决定不这样做以使代码更短。好的,我会的。
        • 这是非常有趣的东西,虽然我无法想象 OP 知道你在做什么!不过,我确信它对其他人有用。
        【解决方案6】:
        def square_array(numbers)
          # Allocate an array with the same size as `numbers`
          # so that the runtime does not have to resize it from time to time
          result = Array.new(numbers.size)
        
          # The index
          i = 0
        
          while i < numbers.size
            # Fill the result array
            result[i] = numbers[i] ** 2
        
            # and don't forget to increase the index,
            # otherwise the loop will run forever.
            i += 1
          end
        
          # Return the result array
          result
        end
        

        【讨论】:

        • 我最好稍后再使用while numbers.shift。与size 不同,这种方法适用于无限输入枚举器。不过,这改变了论点..
        • @AlekseiMatiushkin 我认为保持参数numbers 不变是返回一个新数组的重点,所以我不会使用shift。此外,如果numbers 是一个无限枚举器,那么square_array 将永远不会返回,也许在这种情况下最好给yield 一些东西。
        • 是的,同意。第一行中的numbers.dup 有助于避免变异,但它会破坏惰性枚举,所以老实说我不知道​​。
        • 它看起来像 FORTRAN 但我认为它最接近 OP 想要的。
        • @BobRodes 根据我的基准(1000 万整数平方),预分配比没有预分配快 18%(0.641 秒对 0.781 秒)。此外,Array#map 比简单的 while 循环(没有预分配)快 9%(0.720 秒)。顺便说一句,Array#map 还在后台预先分配了目标数组。
        【解决方案7】:

        简单的方法是map,当然:

        def square_array(numbers)
            numbers.map { |e| e ** 2 }
        end 
        

        但您必须这样做才能对 while 循环执行相同操作(这是一种很好的做法)。

        1. 创建一个数组来包含转换后的数据。
        2. 创建一个计数器(您已经完成了)。
        3. 设置您的while 循环(如您所愿,但最后不需要do)。
        4. 编写一个语句,对索引与计数器相同的数组元素进行平方,并将结果推送到您在步骤 1 中创建的数组中。
        5. 将您的计数器增加 1(您忘记这样做了,因此您将得到一个无限循环,因为 count 将始终等于 0)。
        6. 返回您在步骤 1 中创建的数组。

        这样就可以了!看看你能不能把它放在一起,而不是我只给你代码。

        【讨论】:

          猜你喜欢
          • 2020-12-13
          • 2014-01-23
          • 2014-01-29
          • 1970-01-01
          • 2020-06-28
          • 2011-05-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多