【问题标题】:Rails filtering array of objects by attribute valueRails 按属性值过滤对象数组
【发布时间】:2012-04-09 06:58:48
【问题描述】:

所以我对数据库执行了一个查询,我有一个完整的对象数组:

@attachments = Job.find(1).attachments

现在我有一个对象数组,我不想执行另一个数据库查询,但我想根据Attachment 对象的file_type 过滤数组,这样我就可以获得@987654325 的列表@ 其中文件类型为'logo',然后是另一个attachments 列表,其中文件类型为'image'

类似这样的:

@logos  = @attachments.where("file_type = ?", 'logo')
@images = @attachments.where("file_type = ?", 'image')

但在内存中而不是数据库查询中。

【问题讨论】:

  • 似乎是partition - example here 的一个很好的用例。

标签: ruby-on-rails activerecord


【解决方案1】:

试试:

这很好:

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

但出于性能方面的考虑,您不需要重复 @attachments 两次:

@logos , @images = [], []
@attachments.each do |attachment|
  @logos << attachment if attachment.file_type == 'logo'
  @images << attachment if attachment.file_type == 'image'
end

【讨论】:

  • 由于@Vik 的解决方案非常理想,我将补充一点,在二进制情况下,您可以使用“分区”功能让事情变得更美好。 ruby-doc.org/core-1.9.3/Enumerable.html#method-i-partition
  • 感谢@Vlad,这很酷,但它只支持我们只需要从对象中收集两个东西。
  • 是的,这就是我说“二进制”的原因:)。在问题中,显然可以选择徽标或图像,因此为了完整起见,我添加了这个。
【解决方案2】:

如果你的附件是

@attachments = Job.find(1).attachments

这将是附件对象数组

使用select方法根据file_type进行过滤。

@logos = @attachments.select { |attachment| attachment.file_type == 'logo' }
@images = @attachments.select { |attachment| attachment.file_type == 'image' }

这不会触发任何数据库查询。

【讨论】:

    【解决方案3】:

    您是否尝试过急切加载?

    @attachments = Job.includes(:attachments).find(1).attachments
    

    【讨论】:

    • 对不起,我不清楚:如何在不循环遍历数组的情况下按对象属性的值进行过滤?
    • 如果我理解正确的话,你需要更少的数据库查询,特别是,一旦像@attachments = Job.first.attachments 这样的查询被执行,你想要循环@attachments 同时你不想要更多的数据库查询。这是你想做的吗?
    • 我做一个数据库查询并接收一个对象数组。然后,我想通过根据属性值过滤对象,从该数组中创建两个单独的列表(请参阅原始帖子)-欢呼
    【解决方案4】:

    对于较新版本的 ruby​​,您可以使用

    @logos = @attachments.filter { |attachment| attachment.file_type == 'logo' }
    

    参考:https://apidock.com/ruby/Array/filter

    【讨论】:

      【解决方案5】:

      您可以使用 where 进行过滤

      Job.includes(:attachments).where(file_type: ["logo", "image"])
      

      【讨论】:

        【解决方案6】:

        我会稍微不同。构造您的查询以仅检索您需要的内容并从那里拆分。

        因此,请按照以下方式进行查询:

        #                                vv or Job.find(1) vv
        attachments = Attachment.where(job_id: @job.id, file_type: ["logo", "image"])
        # or 
        Job.includes(:attachments).where(id: your_job_id, attachments: { file_type: ["logo", "image"] })
        

        然后对数据进行分区:

        @logos, @images = attachments.partition { |attachment| attachment.file_type == "logo" }
        

        这将以简洁有效的方式获得您所追求的数据。

        【讨论】:

          猜你喜欢
          • 2019-05-04
          • 2022-08-18
          • 1970-01-01
          • 2016-07-19
          • 2017-11-03
          • 1970-01-01
          • 1970-01-01
          • 2020-01-20
          • 1970-01-01
          相关资源
          最近更新 更多