Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby-Array.find,但返回块中的值_Ruby - Fatal编程技术网

Ruby-Array.find,但返回块中的值

Ruby-Array.find,但返回块中的值,ruby,Ruby,我有一个数组,我想要返回truthy值(aka,而不是nil)的第一个块的结果。问题是,在我的实际用例中,测试有副作用(我实际上在迭代一组队列,并从顶部弹出),因此我不需要在第一次成功之后评估块 a,b,c = [1,2,3] [a,b,c].first_but_value{ |i| (i + 1) == 2 } == 2 a == 2 b == 2 c == 3 有什么想法吗?我怀疑有没有办法做到这一点。问题是Ruby在块中创建了一个闭包,变量i是它的局部变量。执行i+=1可以扩展为i=

我有一个数组,我想要返回truthy值(aka,而不是nil)的第一个块的结果。问题是,在我的实际用例中,测试有副作用(我实际上在迭代一组队列,并从顶部弹出),因此我不需要在第一次成功之后评估块

a,b,c = [1,2,3]

[a,b,c].first_but_value{ |i| (i + 1) == 2 } == 2

a == 2
b == 2
c == 3

有什么想法吗?

我怀疑有没有办法做到这一点。问题是Ruby在块中创建了一个闭包,变量
i
是它的局部变量。执行
i+=1
可以扩展为
i=i+1
,这将在块的范围内创建一个新变量
i
,并且不会修改任何
a、b、c
变量中的值。

这是您想要做的吗

a, b, c = 1, 2, 3

binding.tap { |b|
  break b.local_variable_get [ :a, :b, :c ].find { |sym|
    b.local_variable_set( sym, b.local_variable_get( sym ) + 1 ) == 2
  }
} #=> 2

a #=> 2
b #=> 2
c #=> 3

这是我的看法,这更接近您的实际用例吗?注意
b
的内容是
3
而不是
2
,因为
b
上也调用了带有副作用的
my\u test\u

class MyQueue
  def initialize(j)
    @j = j
  end  
  def my_test_with_side_effect
    (@j+=1) == 2
  end
end

(a,b,c) = [MyQueue.new(1),MyQueue.new(2),MyQueue.new(3)]
[a,b,c].each { |i| break i unless i.my_test_with_side_effect }
=> #<MyQueue:0x007f3a8c693598 @j=3>
a
=> #<MyQueue:0x007f3a8c693980 @j=2>
b
=> #<MyQueue:0x007f3a8c693598 @i=3>
c
=> #<MyQueue:0x007f3a8c693430 @i=3>
类MyQueue
def初始化(j)
@j=j
结束
定义带有副作用的“我的测试”
(@j+=1)==2
结束
结束
(a,b,c)=[MyQueue.new(1),MyQueue.new(2),MyQueue.new(3)]
[a,b,c]每个{i |破坏i,除非i.my | u test(具有| u副作用)
=> #
A.
=> #
B
=> #
C
=> #

find_yield
做你想做的事,检查带有许多核心扩展的ruby方面,特别是
find_yield
可枚举方法:

break
是丑陋的=p

如果您想要功能性方法,您需要一个惰性映射:

[nil, 1, 2, 3].lazy.map{|i| i && i.to_s}.find &:itself   
# => "1"
如果您不认为它没有在整个数组中迭代,只需打印出来并查看:

[nil, 1, 2, 3].lazy.map{|i| (p i) && i.to_s}.find  &:itself
# nil
# 1
# => "1"


用你的块替换
i.to_s

所以他想修改
a
b
c
变量?你怎么知道的?顺便说一句,在Ruby中有一种方法可以完成几乎所有的事情。但是我需要知道询问者想要什么。看起来他们可能在做一个粗糙的断言,他们在代码段的下半部分写了
a==2
,他真的想按块修改局部变量吗?显然我是这么想的。“你为什么不亲自问他?”鲍里斯·蒂尼基:这是我的实际用例。我有一系列生成的重新队列,我想从这些队列中获取第一个作业。因此,如果我使用上面的答案,我想要的是:
job\u data=queue\u name.each{q | job=Resque.pop(q);break job if job}
。这能告诉你我为什么要做这样的事吗?@Sevensacat,请指出我的粗鲁之处,以便我能纠正。你使用的术语我不清楚。“结果”是什么?返回值是多少?还是数组元素?什么是“阻塞的结果”?其次,“truthy”后面的括号让我感到困惑,因为false也不是truthy/truey。其次,“测试有副作用”。我不知道你说的“测试”是什么意思。区块评估?接下来,您“不需要评估第一次成功之外的块”。这不是
#find
方法通常所做的吗?我已经写了一个答案,但我不相信你的要求是真的。最后一句话,
+=
操作符在你的块中没有意义,因为
I
在每次块评估后都会被丢弃。@sevensacat,我用更正式的语气重写了我的评论。内容没有改变。现在音调是否正常?是的,
==
是原始资产。而且我总是忘记露比的<>代码> += 并不总是按照我预期的方式工作(从C++天开始),所以你对我正在试图实现的错误使用是正确的。在实际用例中,它是一个
.pop
,但我觉得这需要额外的背景。“结果”肯定是块的返回值。我不知道还有什么其他方式来解释“结果”。在我的用例中,该块将求值为
nil
,而不是
false
,并且不是所有阅读这些问题的人都会知道
nil
是false这很好。我没想到会用装订。我学到了一些新东西。看见那不是很有趣吗?我以前从来没有遇到过
绑定
,太好了!我得查一下才能明白你的答案,不过谢谢@greyrobot,我让Matz客观化变量。现在看来,我们至少可以明确地知道它的局部变量符号了。我仍然在等待
=
钩子:-)整洁,不知道可以像这样为
break
提供一个值(或者这已经成为循环表达式的值)。这个想法是在Ruby中,break和
return
本质上是一样的。一个用于循环,另一个用于函数上下文。通过打破循环,我们将提前返回。。如果没有带中断符的arg,我们将简单地返回nil,但使用“返回值”,我们可以获得所需的返回行为。(这同样适用于任何循环)小心处理,就像什么也没有找到一样,返回值将是原始数组:
[1,2,3]。每个{i | i+=1;如果i==10,则中断i}=>[1,2,3]
@CarsonReinke easy fix,使用
\35; detect
instead@Kache是的,它一直在那里,很奇怪,很酷!如果/当它被拉到核心ruby中时,弹出返回,因此我可以将其标记为答案。错误,这就是为什么存在
lazy
。使用
lazy
不必映射所有元素。我甚至提供了一个带有打印的版本,这样如果你不相信它,你可以自己测试它。以前没有听说过
lazy
。非常感谢。
[nil, 1, 2, 3].lazy.map{|i| (p i) && i.to_s}.find  &:itself
# nil
# 1
# => "1"