如果传递了一个范围,如何实现一个函数来迭代

Posted

技术标签:

【中文标题】如果传递了一个范围,如何实现一个函数来迭代【英文标题】:how implement a function to iterate over if its passed a Range 【发布时间】:2020-07-05 10:14:18 【问题描述】:

我正在 Ruby 中创建自己的 .each 方法版本,但在实现它以用于 Range (1..10) 的输入时遇到问题。

module Enumerable
  # @return [Enumerable]
  def my_each
    return to_enum :my_each unless block_given?

    index = 0
    while index < size
      if is_a? Array
        yield self[index]
      elsif is_a? Hash
        yield keys[index], self[keys[index]]
      elsif is_a? Range
        yield self[index]
      end
      index += 1
    end
  end
end

如果通过了,我会尝试通过

r_list = (1..10)
r_list.my_each  |number| puts number 

输出将是

=> 
1
2
3
4
5
6
7
8
9
10

【问题讨论】:

each 不在Enumerable 中是有原因的:每个可枚举对象都应该提供自己的eachEnumerable 中的方法可以依靠它来准确地提供迭代对象的元素。也就是说...产生self.begin + index 应该没问题。 对于@Amadan 的评论,请考虑Enumerable#map。还有一种方法Array#map 当然Array 包括Enumerable。我们发现[1].method(:map).owner #=&gt; Array[1].method(:map).super_method.owner #=&gt; Enumerable,所以arr.map ... 调用Array#map。包括Enumerable 的每个类C 都是一样的。 C 已经有一个方法 C#each 所以你的 Enumerable#each 不会被使用。结果是创建Enumerable 方法each 似乎毫无意义。 【参考方案1】:

一种对该实现几乎没有改变的技术是将您的范围转换为数组。

module Enumerable
  def my_each
    return to_enum :my_each unless block_given?

    index = 0
    while index < size
      if is_a? Array
        yield self[index]
      elsif is_a? Hash
        yield keys[index], self[keys[index]]
      elsif is_a? Range
        yield to_a[index]
      end
      index += 1
    end
  end
end

r_list = (1..10)
puts r_list.my_each  |number| puts number 

结果:

1
2
3
4
5
6
7
8
9
10

【讨论】:

以上是关于如果传递了一个范围,如何实现一个函数来迭代的主要内容,如果未能解决你的问题,请参考以下文章

如何推导出 std::advance 迭代器类型?

将空范围传递给采用一对迭代器的函数的简洁/简洁的方法是啥?

c# 请问数组能作为参数传递吗? 如果可以如何传递呢?

使用lambda函数进行向量排序,当不在同一范围内时如何传递变量来捕获组?

使用 aiohttp.post 我如何传递一些数据进行迭代

在范围内通过回调函数传递数据