映射/收集第一个真实结果

时间:2013-08-06 11:34:27

标签: ruby-on-rails ruby

考虑以下

users.collect do |user|
  user.favorite_song.presence
end.compact.first

在这种情况下,我想要在用户中遇到我喜欢的第一首歌。

这可以用更好的方式写出来吗?

我试过

users.find do |user|
  user.favorite_song.presence
end

但它会返回第一个拥有喜欢的歌曲的用户,而不是最喜欢的歌曲。

5 个答案:

答案 0 :(得分:10)

如果users数组不是太大,那么您的第一个解决方案就可以了,可以像这样重写:

users.map(&:favorite_song).compact.first

您还可以按如下方式修改第二种方法:

users.find { |user| user.favorite_song.present? }.favorite_song

这两个解决方案都假设某些用户中存在favorite_song,如果没有,则会引发异常。您可以使用try(仅限Rails)优雅地避免这种情况:

users.find { |user| user.favorite_song.present? }.try(:favorite_song)

答案 1 :(得分:4)

怎么样:

users.each do |user|
  break user.favorite_song if user.favorite_song.present?
end

如果条件为user.favorite_song,则会返回true,否则将返回users

答案 2 :(得分:1)

favorite_song = nil
users.map do |user|
  favorite_song = user.favorite_song
  break if favorite_song
end

答案 3 :(得分:0)

请试试

users.map{|user| user.favorite_song}.compact.first

答案 4 :(得分:0)

从Ruby 2.0开始,您可以使用Enumerator::Lazy#lazy来更清晰有效地解决这个问题:

users.lazy.map(&:favorite_song).find(&:present?)

这样效率更高,因为它只会在用户上找到favorite_song,直到找到一个存在的用户。它更清晰,因为它更简洁,lazy是自我记录的意图。