有{| x | x}红宝石的速记?

时间:2014-01-29 05:56:33

标签: ruby

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

后者是找到数组中第一个真实的项目 目前我只是使用.compact.first,但我觉得必须有一种优雅的方式来使用find,例如我find(&:to_bool).find(true)我缺少。 使用.find(&:nil?)有效,但与我想要的相反,我找不到与#find或#detect相反的方法,或像#true这样的方法?

那么有更优雅的方式来编写.find{ |x| x }吗?如果没有,我会坚持.compact.first
(我知道compact不会删除false,但这对我来说不是问题,也请避免使用rails方法)

编辑:对于我的确切情况,它仅用于字符串和nils的数组,例如
[nil, "x", nil, nil, nil, nil, "y", nil, nil, nil, nil] => "x"

6 个答案:

答案 0 :(得分:2)

没有。

如果tap无障碍地工作,你可以这样做:

array.detect(&:tap)

但事实并非如此。无论哪种方式,我认为你所拥有的是非常简洁,惯用的,并且碰巧与上述非工作的替代品具有相同数量的字符,因此你应该坚持:

array.compact.first

你可以通过猴子补丁来获得更短的版本,但是对于那些熟悉Ruby的人来说,它变得不清楚,这可能不值得轻微的“节省”。

好奇心,如果你碰巧想要array.detect { |x| !x }(相反),你可以这样做:

array.detect(&:!)

这是有效的,因为!x实际上是x.!的简写。当然,这只会给你nilfalse,这可能不是很有用。

答案 1 :(得分:2)

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

然而,您要求的新功能尚未在Ruby中提供。它存在于Ruby路线图中:

https://bugs.ruby-lang.org/issues/6373

预计在2035-12-25之前实施,你能等一下吗?

话虽如此,打字的次数是group_by{|x|x}

编辑:

正如Stefan指出的那样,自Object#itself引入以来,我对Ruby 2.2及更高版本的回答更长。

答案 2 :(得分:1)

不,没有。我个人有一个实用程序库,我在所有项目中都包含了类似

的项目
IDENTITIY = -> x { x }

然后你会

.group_by(&IDENTITY)

有一个长期的错误报告,用于向Object添加只返回self的方法,但是,没有人能够为matz满足的方法找到一个名称。假设该方法被称为self,那么您也可以说

.group_by(&:self)

答案 3 :(得分:0)

可能你正在寻找Enumerable#detect,这更加语义化了:

array.detect { |x| x }

出于好奇,一个monkeypatch:

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

array.detect &:not_pure?

答案 4 :(得分:0)

虽然该标记适用于ruby - 使用Rails(更具体地说是ActiveSupport),您将获得一个方法presence,该方法适用于对present?做出积极响应的任何内容(这将排除空白字符串,数组,哈希等):

array.find(&:presence)

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

答案 5 :(得分:0)

我经常使用group_by,map,select,sort_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