我在Ruby(1.9.2)中有两个来自两个不同来源(二进制数据)的长数据流.
这两个源以两个枚举器的形式封装.
我想检查两个流是否完全相同.
我有几个解决方案,但两者看起来都很不优雅.
第一个简单地将两者转换为数组:
def equal_streams?(s1, s2)
s1.to_a == s2.to_a
end
Run Code Online (Sandbox Code Playgroud)
这是有效的,但它在内存方面并不是非常高效,特别是如果流有很多信息.
另一种选择是......呃.
def equal_streams?(s1, s2)
s1.each do |e1|
begin
e2 = s2.next
return false unless e1 == e2 # Different element found
rescue StopIteration
return false # s2 has run out of items before s1
end
end
begin
s2.next
rescue StopIteration
# s1 and s2 have run out of elements at the same time; they are equal
return true
end
return false
end
Run Code Online (Sandbox Code Playgroud)
那么,有没有更简单,更优雅的方式呢?
saw*_*awa 10
假设您的流不包含元素,只需对您的代码进行轻微的重构:eof
.
def equal_streams?(s1, s2)
loop do
e1 = s1.next rescue :eof
e2 = s2.next rescue :eof
return false unless e1 == e2
return true if e1 == :eof
end
end
Run Code Online (Sandbox Code Playgroud)
使用类似关键字loop
应该比使用类似方法更快each
.
比较它们一次一个元素可能是你能做的最好的,但你可以做得比你的"呃"解决方案更好:
def grab_next(h, k, s)
h[k] = s.next
rescue StopIteration
end
def equal_streams?(s1, s2)
loop do
vals = { }
grab_next(vals, :s1, s1)
grab_next(vals, :s2, s2)
return true if(vals.keys.length == 0) # Both of them ran out.
return false if(vals.keys.length == 1) # One of them ran out early.
return false if(vals[:s1] != vals[:s2]) # Found a mismatch.
end
end
Run Code Online (Sandbox Code Playgroud)
棘手的部分是区分一个用完的流和两个用完的流.将StopIteration
异常推入单独的函数并使用哈希中缺少键是一种相当方便的方法.vals[:s1]
如果您的流包含false
或nil
只是检查是否存在密钥解决该问题,只是检查将导致问题.