简体   繁体   English

如何用ruby重写每个循环?

[英]How to rewrite this each loop in ruby?

I have this loop: 我有这个循环:

  stations = Station.where(...)
  stations.all.each do |s|
    if s.city_id == city.id
      show_stations << s
    end
  end

This works well, but because of looping the all the data, I think it's kinda slow. 这很好用,但是由于循环所有数据,我认为这有点慢。 I've tried to rewrite it with using select , like this: 我尝试使用select重写它,如下所示:

show_stations << stations.select { |station| station.city_id == city.id}

But the amount of saved data into show_stations is different compared to the each version and then, the data are in different format (array/object). 但是与each版本相比,保存到show_stations数据量有所不同,因此数据的格式(数组/对象)不同。

Is there any better/faster way to rewrite the loop version? 有没有更好/更快的方法来重写循环版本?

The fastest version of this maybe the built-in rails ActiveRecord method for finding associated objects. 最快的版本可能是用于找到关联对象的内置rails ActiveRecord方法。

So provided your Station model contains this: 因此,只要您的Station模型包含以下内容:

class Station < ActiveRecord::Base
  belongs_to :city

And your City model contains this: 您的城市模型包含以下内容:

class City < ActiveRecord::Base
  has_many :stations

Then rails automatically generates the method city.stations which automatically fetches the stations which contain that city's id from the database. 然后,rails自动生成方法city.stations ,该方法自动从数据库中获取包含该城市ID的站点。 It should be pretty optimized. 它应该是相当优化的。
If you want to make it even faster then you can add add_index :stations, :city_id to your table in a migration and it will retrieve faster. 如果要使其更快,则可以在迁移中将add_index :stations, :city_id到表中,它将更快地检索。 Note that this only saves time when you have a lot of stations to search through. 请注意,这仅在您有大量要搜索的电台时才节省时间。

If you need to make it an array you can just convert it after with city.stations.to_a . 如果需要将其设置为数组,则可以在之后使用city.stations.to_a对其进行转换。 And if you wanted to narrow it further, just use the select method and add the conditions that you wanted to previously add in your Station.where(...) statement. 并且,如果您想进一步缩小范围,只需使用select方法并在Station.where(...)语句中添加之前要添加的条件。
(eg city.stations.to_a.select { |item| your_filter } ) (例如city.stations.to_a.select { |item| your_filter }

您还应该缓存查询结果,例如

    stations ||= Station.where("your where").where(:city_id => city.id)

Station appears to be an active record model. Station似乎是一个活动记录模型。 If that is the case, and you don't need all the stations, you can add the city.id filter to your where statement. 如果是这种情况,并且不需要所有站点,则可以将city.id过滤器添加到where语句中。

The issue you're having now is that you're adding the array returned from select as the last item of show_stations . 现在遇到的问题是,您要将select返回的数组添加为show_stations的最后一项。 If you want show_stations to only contain stations that match city.id then use show_stations = ... rather than show_stations << ... . 如果要让show_stations只包含与city.id匹配的电台, city.id使用show_stations = ...而不是show_stations << ... If you want show_stations to contain what it already contains plus the stations that match city.id then use show_stations + stations.select { |station| station.city_id == city.id } 如果希望show_stations包含已经包含的内容以及与city.id匹配的站点, city.id使用show_stations + stations.select { |station| station.city_id == city.id } show_stations + stations.select { |station| station.city_id == city.id } . show_stations + stations.select { |station| station.city_id == city.id } (There are a number of other approaches for adding two arrays together.) (还有许多其他方法可以将两个数组加在一起。)

Maybe you need to include into the where clause the city parameter: 也许您需要在where子句中包含city参数:

stations = Station.where("your where").where(:city_id => city.id)

or the same 或相同

stations = Station.where("your where").where('city_id = ?', city.id)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM