【发布时间】:2016-12-24 18:58:47
【问题描述】:
我真的需要使用类似于Single 方法的东西,它:
返回一个序列的唯一元素,如果序列中不完全是一个元素,则抛出异常。
显然,为了方便起见,我可以添加扩展/改进。
但是类似的东西已经存在了吗? 也许在 ActiveSupport 或其他库中?
【问题讨论】:
标签: ruby monkeypatching enumerable refinements
我真的需要使用类似于Single 方法的东西,它:
返回一个序列的唯一元素,如果序列中不完全是一个元素,则抛出异常。
显然,为了方便起见,我可以添加扩展/改进。
但是类似的东西已经存在了吗? 也许在 ActiveSupport 或其他库中?
【问题讨论】:
标签: ruby monkeypatching enumerable refinements
不,标准库中没有任何内容(我相信 ActiveSupport 也没有),但很容易实现。
module EnumeratorWithSingle
class TooManyValuesException < StandardError; end
class NotEnoughValuesException < StandardError; end
refine Enumerator do
def single
val = self.next
begin
self.next
raise TooManyValuesException
rescue StopIteration
val
end
rescue StopIteration
raise NotEnoughValuesException
end
end
end
module Test
using EnumeratorWithSingle
puts [1].each.single # 1
puts [1, 2].each.single # EnumeratorWithSingle::TooManyValuesException
end
【讨论】:
e = [1, 2].each; e.next; puts e.single 打印 2,这可能不是我们想要的结果。
begin 作为single 的第一行吗?现在,如果self #=> [].to_enum、self.next 将引发一个不会被处理的StopIteration 异常。
single的第一行应该是self_cpy = dup,然后对self.cpy进行操作。
begin...end 在def 级别是可选的。注意缩进。在每种情况下处理StopIteration(包括[].each.single);自己试试吧。
Enumerator#single,而Enumerator 可能是可倒带的,也可能不是。因此,您实际上别无选择。对我来说,Enumerator#single 应该说“枚举器中只剩下一个值”。如果你想测试一个容器是否有一个值,它应该属于Enumerable#single,你知道self.each会给你整个序列。