排序数组时出现问题

时间:2011-07-02 14:26:11

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

我正在混合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属性和{{排序底部的1}}按其@current_user_statuses属性排序。

这是观点:

created_at

5 个答案:

答案 0 :(得分:3)

尝试:

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

答案 1 :(得分:1)

你不能像这样以flatten!方式菊花链。如果未对数组进行任何更改,则flatten!将返回nil。当你排序零时,什么都不会发生。

您需要将它们分开:

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

答案 2 :(得分:0)

我是这样做的:

设置课程:

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的状态,加上所有朋友的状态,然后展平它。

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

答案 3 :(得分:0)

@statuses = (@current_user_statuses + @friends_statuses).sort_by(&:created_at)

答案 4 :(得分:0)

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

方法1:简洁明了

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