Ruby的sort_by可以按多个字段排序

41

我正在运行 Ruby 1.9.3p392。

Item = Struct.new( :name, :dir, :sort_dir )

entries = ftp.list()
entries.map!{|e| Net::FTP::List.parse(e) }.map!{|e| Item.new( e.basename, e.dir?, (e.dir? ? 0 : 1) ) }

render json: entries.sort_by{ |e| [ e.sort_dir, e.name ]}

由于某些原因,我未能按预期获得结果。

我首先获取所有文件夹,然后是所有文件,但名称排序失败。

例如,下面是我获取的文件夹:

  1. content
  2. images
  3. bin

对于文件:

  1. global.asax
  2. web.config
  3. favicon.ico

它正确地组合了目录/文件部分,但名称排序不正确。

在排序后,控制台输出如下:

#<struct FtpController::Item name="Content", dir=true, sort_dir=0>
#<struct FtpController::Item name="Images", dir=true, sort_dir=0>
#<struct FtpController::Item name="Scripts", dir=true, sort_dir=0>
#<struct FtpController::Item name="Views", dir=true, sort_dir=0>
#<struct FtpController::Item name="bin", dir=true, sort_dir=0>
#<struct FtpController::Item name="Global.asax", dir=false, sort_dir=1>
#<struct FtpController::Item name="Web.config", dir=false, sort_dir=1>
#<struct FtpController::Item name="favicon.ico", dir=false, sort_dir=1>
#<struct FtpController::Item name="packages.config", dir=false, sort_dir=1>
#<struct FtpController::Item name="robots.txt", dir=false, sort_dir=1>
1个回答

78

你的排序在MRI Ruby 1.8.7、1.9.3和2.0.0中都能正常工作:

Item = Struct.new(:name, :dir, :sort_dir)

entries = [Item.new('favicon.ico', false, 1), Item.new('bin', true, 0),
           Item.new('web.config', false, 1), Item.new('images', true, 0),
           Item.new('global.asax', false, 1), Item.new('content', true, 0)]

entries.sort_by{|e| [e.sort_dir, e.name]}
# => [#<struct Item name="bin", dir=true, sort_dir=0>,
#     #<struct Item name="content", dir=true, sort_dir=0>,
#     #<struct Item name="images", dir=true, sort_dir=0>,
#     #<struct Item name="favicon.ico", dir=false, sort_dir=1>,
#     #<struct Item name="global.asax", dir=false, sort_dir=1>,
#     #<struct Item name="web.config", dir=false, sort_dir=1>]

你尝试将sort_by的结果输出到控制台了吗?我不熟悉你代码中的render json:部分,但也许问题就出在那里。最可能的情况是,在转换为 JSON 时(如果确实这样做了),排序顺序被搞乱了。

另一个想法是,也许你希望sort_by修改entries,但它并没有这样做。如果你想要调用之后entries本身被排序,请使用sort_by!(注意方法名末尾的!)。

更新:看起来问题出在你想要执行大小写不敏感的搜索。只需添加upcase即可解决问题:

entries.sort_by{|e| [e.sort_dir, e.name.upcase]}

我将控制台输出包含在原始问题中。此外,我不希望条目本身被排序。我期望它返回一个已排序的列表给渲染方法。然而,我得到的JSON和控制台输出是匹配的。 - Mike
@Mike 看起来问题是你想要一个不区分大小写的排序,对吧?因为你的输出已经排序了,只是大写字母在前。 - Darshan Rivka Whittle
你能将你的评论作为答案添加,这样我就可以将其标记为正确了。我在名称中添加了小写字母,并且它按预期工作。谢谢! - Mike
如何将此代码改为三个条件排序,且不同条件需要不同的顺序?例如,我有一个数据库条目,其中包含日期、时间戳和状态列。我想按照日期(降序)、状态(升序)和时间(升序)对结果进行排序。日期不是实际列,我正在使用timestamp.to_date检索日期。尝试使用以下代码: 'code'@results = @results.sort_by { |x| [-x.timestamp.to_date, x.status, x.timestamp]} 以获得所需的顺序失败,因为x.timestamp.to_date不是整数。 - anubhav16

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接