ruby中有{x}速记吗?

ruby中有{x}速记吗?,ruby,Ruby,我经常使用.group_by{x | x}和.find{x | x} 后者是在数组中查找第一个为真的项。 目前我只是在使用.compact。首先,但我觉得必须有一种优雅的方式来使用find here,比如find(&:to bool)或.find(true),我缺少的。 使用.find(&:nil?可以工作,但与我想要的正好相反,我找不到与#find或#detect相反的方法,或者像#true 那么,有没有更优雅的方式来编写。查找{x | x}?如果没有,我将坚持使用.compact.first

我经常使用
.group_by{x | x}
.find{x | x}

后者是在数组中查找第一个为真的项。
目前我只是在使用
.compact。首先
,但我觉得必须有一种优雅的方式来使用find here,比如
find(&:to bool)
.find(true)
,我缺少的。
使用
.find(&:nil?
可以工作,但与我想要的正好相反,我找不到与#find或#detect相反的方法,或者像#true

那么,有没有更优雅的方式来编写
。查找{x | x}
?如果没有,我将坚持使用
.compact.first

(我知道compact不会删除
false
,但这对我来说不是问题,也请避免使用rails方法)

编辑:就我的具体情况而言,它仅用于字符串和零的数组,例如

[nil,“x”,nil,nil,nil,nil,“y”,nil,nil,nil,nil,nil]
=>“x”

可能是您在寻找的,这更具语义:

array.detect { |x| x }
出于好奇,monkeypatch:

class ::Object
  def not_pure?
    !!self
  end
end

array.detect &:not_pure?
没有

如果在没有障碍物的情况下工作,您可以:

array.detect(&:tap)
array.detect(&:!)
但事实并非如此。不管怎样,我认为您所拥有的都是非常简洁、惯用的,并且恰好与上述非工作选项的字符数相同,因此您应该坚持:

array.compact.first
你可以通过修补程序来获得一个较短的版本,但是对于其他熟悉Ruby的人来说,这就变得不清楚了,因为这可能不值得一点点的“节省”

好奇的是,如果您碰巧想要
array.detect{x |!x}
(相反),您可以执行以下操作:

array.detect(&:tap)
array.detect(&:!)

这是因为
!x实际上是x的缩写。当然,这只会给您提供
nil
false
,这可能不是很有用。

如果您不关心返回的内容,有时可以使用
哈希方法

然而,您所要求的功能在Ruby中还不可用。它出现在Ruby路线图中:

预计在2035年12月25日前实施,你能等一下吗

也就是说,按{x{x}
分组需要多少打字

编辑:


正如Stefan所指出的,自从引入了
对象本身以来,我的答案现在对Ruby 2.2及以上版本不再有效了。我个人有一个实用程序库,我把它包含在我所有的项目中

IDENTITIY = -> x { x }
那你会的

.group_by(&IDENTITY)
还有一个
Object#本身
,它只返回
self

.group_by(&:itself)

尽管标签是针对
ruby
——使用Rails(更具体地说是ActiveSupport),您会得到一个方法
presence
,它将适用于任何对
present?
做出积极响应的方法(这将排除空白字符串、数组、哈希等):


它并不完全等同于首选结果,但它适用于我遇到的大多数情况。

我经常使用group\u by、map、select、sort\u by和其他各种散列方法。昨天,我在一个类似的问题上反复尝试另一个答案,发现了这个有用的小扩展:

class Hash
  def method_missing(n)
    if has_key? n
      self[n]
    else
      raise NoMethodError
    end
  end
end
对于任何由ruby创建的哈希,或者任何已由as_json进行jsonified的数据,这个添加允许我编写稍微短一点的代码。例如:

# make yellow cells
yellow = red = false
tube_steps_status.group_by(&:step_ordinal).each do |type|
    group = type.last.select(&:completed).sort_by(&:completed)
    red = true if group.last.step_status == 'red' if group.any?
    yellow = true if group.map(&:step_status).include?('red')
end
tube_summary_status = 'yellow' if yellow unless red

我真的不知道你想要什么样的速记<代码>{| x | x}
不够短吗?经过一段时间后,试图缩短代码会适得其反。我总是在这里使用较长的选项,
.compact.first
。我想你是对的,只是ruby通常有一种很好的方法来处理这样的事情,我想我忽略了一种。这有点像黑客,但我认为
(&:dup)
适用于可变对象。例如:
%w[a b a d b].group_by(&:dup)=>{“a”=>[“a”,“a”],“b”=>[“b”,“b”],“d”=>[“d”]}
。我读到了Ruby的一些计划,可以很好地做到这一点。@CarySwoveland复制每个元素可能有点昂贵。总是有
ident=lambda{x}
groupby(&ident)
,但这有点毫无意义,除非,您有一大串方法调用,并且已经将逻辑分解为lambda。#detect是#find的别名-我只是在寻找一种较短的方法来实现这一点,但在最坏的情况下,它会……)@user21033168 detect不是别名,它将
Proc
实例作为参数;但我明白你的意思。@mudasobwa find也需要一个过程,它们只是别名。至少在ruby 2中。0@user21033168好啊我用一个愚蠢的monkeypatch更新了一个答案。
array.detect(&:tap)
gives
LocalJumpError:no block gived
该死,我以为你破解了它,但不幸的是,我得到了
tap:
no block gived(LocalJumpError)
这就是我写答案而不在深夜运行它的结果。哦,好吧。不过,我在回答中的最后一句话仍然有效:
compact.first
的字符数是相同的,我认为不会比core Ruby短。你可以使用monkey patch,但它不太地道,可能不值得。为了给评论阅读时间,我会在某个时候删除这个答案。@Andrew Marshall即使
.find(&:tap)
有效,
.compact.first
的速度实际上是原来的两倍,这让我非常惊讶。(我对
.find{x | x}
vs
.compact.first
)进行了基准测试。是的,我认为
.compact。首先,
仍然是最好的方法,除非有人能提出一个像您这样的简短优雅的解决方案。@user21033168我放弃了删除我的答案,而是果断地说,您想要的东西目前没有速记,您应该坚持使用
:)
。好消息。我将倒计时,正好还剩8000天。第一句话非常重要,因为
nil.hash
&
false.hash
返回数字