【问题标题】:Problem sorting an array数组排序问题
【发布时间】:2011-09-27 07:21:31
【问题描述】:

我正在混合 2 个数组,并希望通过它们的 created_at 属性对它们进行排序:

@current_user_statuses = current_user.statuses
@friends_statuses = current_user.friends.collect { |f| f.statuses }
@statuses = @current_user_statuses + @friends_statuses
@statuses.flatten!.sort!{ |a,b| b.created_at <=> a.created_at }

@current_user_statuses@friends_statuses 均正确排序,但它们组合起来排序不正确,@friends_statuses 始终按其created_at 属性排序显示在顶部,@current_user_statuses 按其@ 排序在底部987654327@属性。

这是视图:

<% @statuses.each do |d| %>
<%= d.content %>
<% end %>

【问题讨论】:

  • 对不起,我真的很难理解问题所在。您介意在第一个代码示例之后改写文本吗?
  • “好友状态始终显示在顶部,按属性创建的位置排序,底部的 current_user_statuses 按属性创建的位置排序”--- 并且 created_at 中的时间表明记录应该混在一起?
  • @gal,请显示所需的结果。谢谢。
  • 发布示例输出,以便我们查看日期。您是否检查过以确保它们不是偶然以这种方式订购的?
  • 除非您展示了正在测试的数据的良好样本,否则我们无法为您提供进一步的帮助。告诉所有回答“排序不是我的问题......我的朋友状态总是显示在顶部”的人并没有帮助。花时间提供完整的数据样本。

标签: ruby-on-rails ruby ruby-on-rails-3


【解决方案1】:

试试:

(current_user.statuses + current_user.friends.collect(&:statuses)) \
  .flatten.compact.sort_by(&:created_at)

【讨论】:

  • 排序不是我的问题...我的朋友状态总是显示在顶部...
【解决方案2】:

你不能像这样菊花链flatten! 方法。如果没有对数组进行更改,flatten! 返回 nil。当你排序 nil 时,什么都不会发生。

你需要将它们分开:

@statuses.flatten!
@statuses.sort! { ... }

【讨论】:

  • 非常正确,尽管这并不是问题的真正答案;) 当您排序 nil 时,您将得到 NoMethodError
【解决方案3】:

我会这样做:

设置类:

class User

  class Status
    attr_reader :statuses, :created_at
    def initialize(stats)
      @statuses = stats
      @created_at = Time.now
    end
  end

  attr_reader :statuses, :friends
  def initialize(stats=[], friends=[])
    @statuses = Status.new(stats)
    @friends = friends
  end
end

定义一些实例,只是为了好玩:

friend2 = User.new(%w[yellow 2])
sleep 1
friend1 = User.new(%w[orange 1])
sleep 2
current_user = User.new(%w[green 1], [friend1, friend2])

以下是我的不同做法;以created_at 顺序获取状态:

statuses = [
  current_user.statuses, 
  current_user.friends.collect(&:statuses)
].flatten.sort_by(&:created_at)

看起来像:

require 'pp'
pp statuses

# >> [#<User::Status:0x0000010086bd60
# >>   @created_at=2011-07-02 10:49:49 -0700,
# >>   @statuses=["yellow", "2"]>,
# >>  #<User::Status:0x0000010086bc48
# >>   @created_at=2011-07-02 10:49:50 -0700,
# >>   @statuses=["orange", "1"]>,
# >>  #<User::Status:0x0000010086bb30
# >>   @created_at=2011-07-02 10:49:52 -0700,
# >>   @statuses=["green", "1"]>]

我只是构建一个临时包含数组来保存 current_user 的状态,加上所有朋友的状态,然后将其展平。

(&amp;:statuses)(&amp;:created_at) 参数是Rails 对实例的statuses 方法或实例的created_at 方法的简写。

【讨论】:

  • 排序不是我的问题...我的朋友状态总是显示在顶部...
  • 其实排序是你代码中的一个问题。您使用的是sort 而不是sort_by,这在处理数据结构或对象时速度要慢得多。
【解决方案4】:
@statuses = (@current_user_statuses + @friends_statuses).sort_by(&:created_at)

【讨论】:

  • 排序不是我的问题...我的朋友状态总是显示在顶部...
  • 请通过提供p statuses.map(&amp;:created_at)的输出来证明这一点
【解决方案5】:

我知道针对您的问题发布了几种解决方案。但是,当状态数量增加时,所有这些解决方案都会杀死您的系统。对于这个数据集,您必须在数据库层而不是在 Ruby 层中执行排序和分页

方法一:简单明了

Status.find_all_by_user_id([id, friend_ids].compact, :order => :created_at)

方法 2:长期高效

class User    
  def all_statuses
    @all_statuses ||=Status.all( :joins => "JOIN (
        SELECT friend_id AS user_id 
        FROM   friendships 
        WHERE  user_id = #{self.id}
      ) AS friends ON statuses.user_id = friends.user_id OR 
                      statuses.user_id = {self.id}",
      :order => :created_at
    )
  end    
end

现在您可以在单个查询中获取排序状态:

user.all_statuses

PPS:如果这是我的代码,我会进一步优化 SQL。有关更多详细信息,请参阅此answer

【讨论】:

  • 排序不是我的问题...我的朋友状态总是显示在顶部...
  • 如果你使用我建议的方法,只有当朋友的状态比你的状态新时才会发生这种情况。
猜你喜欢
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 2013-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多