我经常使用.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"
答案 0 :(得分:2)
没有。
如果tap
无障碍地工作,你可以这样做:
array.detect(&:tap)
但事实并非如此。无论哪种方式,我认为你所拥有的是非常简洁,惯用的,并且碰巧与上述非工作的替代品具有相同数量的字符,因此你应该坚持:
array.compact.first
你可以通过猴子补丁来获得更短的版本,但是对于那些熟悉Ruby的人来说,它变得不清楚,这可能不值得轻微的“节省”。
好奇心,如果你碰巧想要array.detect { |x| !x }
(相反),你可以这样做:
array.detect(&:!)
这是有效的,因为!x
实际上是x.!
的简写。当然,这只会给你nil
或false
,这可能不是很有用。
答案 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