我想对数组进行排序,以升序或降序排序。 我的数组包含哈希键,我要排序的值是float,integer和string(名称)。名称可以是字母或字母数字。我想创建一个可以处理所有排序的方法。它将采用数组,列名和排序顺序,并返回已排序的其余数组。 以下是JSON输出。我的数组包含哈希键。
[
{
"sid": "101",
"snumber": "798798",
"name": "Anita 1",
"time": 1800,
"count": 32,
"hour": "",
"avg": 1
},
{
"sid": "160",
"snumber": "6546546",
"name": "Anita 22",
"time": 1300,
"count": 30,
"hour": "1",
"avg": 1
},
{
"sid": "120",
"snumber": "6546546",
"name": "Anita",
"time": 2300,
"count": 10,
"hour": "2",
"avg": 2
}
]
我尝试了很多事情,但是做错了什么。这是我的方法:
def self.sort_by_alphabets(arr, sortColumnName, sortOrder) # sortOrder a: ASC,d: DESC
column = sortColumnName.to_sym
return arr.sort_by { |h|
if sortColumnName == 'sid' || sortColumnName = 'snumber' || sortColumnName =='hour'
a = h[column].to_i
else
if h[column].is_a? String
a = h[column].to_s
type ='s'
elsif h[column].is_a? Float
a = h[column].to_f
type ='f'
else
a = h[column].to_i
type ='i'
end
if sortOrder == 'a'
a.downcase
else
a.upcase
end
}
end
有人可以帮我吗?
期望的输出是排序数组。假设如果我想使用sid
来对数组进行升序排序,则结果数组将按上述顺序按sid进行排序,其他键也是如此。但是,一次只能将数组按任何一个键排序。
答案 0 :(得分:3)
代码
def sort_by_value(arr, key, ascending = true)
arr.sort_by do |h|
v = h[key]
raise TypeError, "#{v}.class => #{v.class} invalid" unless
(v.kind_of?(Numeric) && !v.is_a?(Complex)) || v.is_a?(String)
Float(v) rescue v.downcase
end.tap { |a| a.reverse! if ascending == false }
end
请参见Enumerable#sort_by,Object#kind_of?和Kernel#Float。
我假设当值是代表数字值(不是复数)的字符串时,将对关联的数字进行排序。 Float(v)
尝试将字符串v
转换为浮点数。如果成功,则返回float;否则,它将引发被抢救的异常(行内),从而导致返回v.downcase
。
示例
arr = [
{ "name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=> "79", "fnbr"=>"-2.31" },
{ "name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=> "654", "fnbr"=>"12.4" },
{ "name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2" }
]
sort_by_value(arr, "name")
#=> [{"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79","fnbr"=>"-2.31"}
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654","fnbr"=>"12.4"},
# {"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654","fnbr"=>"-1284e-2"}]
sort_by_value(arr, "name", false)
#=> [{"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"},
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"}]
sort_by_value(arr, "time")
#=> [{"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"}]
sort_by_value(arr, "time", false)
#=> [{"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"}]
sort_by_value(arr, "wt")
#=> [{"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"}]
sort_by_value(arr, "wt", false)
#=> [{"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"}]
sort_by_value(arr, "inbr")
#=> [{"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"}]
sort_by_value(arr, "inbr", false)
#=> [{"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"}]
sort_by_value(arr, "fnbr")
#=> [{"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"}]
sort_by_value(arr, "fnbr", false)
#=> [{"name"=>"Anita 22", "time"=>13, "wt"=>-12.4, "inbr"=>"654", "fnbr"=>"12.4"},
# {"name"=>"Anita 1", "time"=>18, "wt"=>2.31, "inbr"=>"79", "fnbr"=>"-2.31"},
# {"name"=>"bubba", "time"=>23, "wt"=>12.84, "inbr"=>"-654", "fnbr"=>"-1284e-2"}]
答案 1 :(得分:0)
ary = [{
"sid" => "101",
"snumber" => "798798",
"name" => "Ben",
"time" => 1800,
"count" => 32,
"hour" => "",
"avg" => 1
},
{
"sid" => "160",
"snumber" => "6546546",
"name" => "anita",
"time" => 1300,
"count" => 30,
"hour" => "1",
"avg" => 1
},
{
"sid" => "120",
"snumber" => "6546546",
"name" => "Jake",
"time" => 2300,
"count" => 10,
"hour" => "2",
"avg" => 2
}]
我假设您想按任何列进行排序,无论其值是数字还是字符串。我不知道您为什么尝试使用downcase
。如果那有特殊含义,请提及。我将更新答案。
def sort_by_key(ary, column, order)
# I am working on hashes with stringified keys, so not doing `to_sym` on `column`. You can uncomment below line if your hashes has symbol keys.
# column = column.to_sym
order = order.to_sym
raise 'Unknown sort order' unless %i[asc desc].include?(order)
ary.sort do |x, y|
order == :asc ?
x[column] <=> y[column] :
y[column] <=> x[column]
end
end
sort_by_key(ary, 'sid', :desc)
=> [{"sid"=>"160", "snumber"=>"6546546", "name"=>"anita", "time"=>1300, "count"=>30, "hour"=>"1", "avg"=>1},
{"sid"=>"120", "snumber"=>"6546546", "name"=>"Jake", "time"=>2300, "count"=>10, "hour"=>"2", "avg"=>2},
{"sid"=>"101", "snumber"=>"798798", "name"=>"Ben", "time"=>1800, "count"=>32, "hour"=>"", "avg"=>1}]
sort_by_key(ary, 'name', :asc)
=> [{"sid"=>"101", "snumber"=>"798798", "name"=>"Ben", "time"=>1800, "count"=>32, "hour"=>"", "avg"=>1},
{"sid"=>"120", "snumber"=>"6546546", "name"=>"Jake", "time"=>2300, "count"=>10, "hour"=>"2", "avg"=>2},
{"sid"=>"160", "snumber"=>"6546546", "name"=>"anita", "time"=>1300, "count"=>30, "hour"=>"1", "avg"=>1}]
查看“ anita”如何排在最后,因为默认情况下所有大写字母排在小写字母之前。
如果要对名称进行排序(不区分大小写),请如下修改方法:
def sort_by_key(ary, column, order)
...
ary.sort do |x, y|
val_x, val_y = [x, y].map { |hash| hash[column] }
val_x, val_y = [val_x, val_y].map(&:downcase) if [val_x, val_y].all? { |v| v.respond_to?(:downcase) }
order == :asc ?
val_x <=> val_y :
val_y <=> val_x
end
end
sort_by_key(ary, 'name', :asc)
=> [{"sid"=>"160", "snumber"=>"6546546", "name"=>"anita", "time"=>1300, "count"=>30, "hour"=>"1", "avg"=>1},
{"sid"=>"101", "snumber"=>"798798", "name"=>"Ben", "time"=>1800, "count"=>32, "hour"=>"", "avg"=>1},
{"sid"=>"120", "snumber"=>"6546546", "name"=>"Jake", "time"=>2300, "count"=>10, "hour"=>"2", "avg"=>2}]
注意:您将键"hour"
的值存储为字符串。因此,排序将像其他任何字符串一样对它们进行处理"hour"
值“ 12”将先于值“ 2”。要解决此问题,您可以使用String#to_i
将"hour"
的字符串值转换为整数。
答案 2 :(得分:0)
如果要修补数组类,可以执行以下操作,例如:
module ArrayPatch
def sort_by_key(key, order = :asc)
sorted = sort_by { |hash| hash[key] }
sorted.reverse! if order == :desc
sorted
end
end
Array.include ArrayPatch
默认订单为:asc
,可以跳过order参数:
array.sort_by_key(:name)
# => [{:sid=>"120", :snumber=>"6546546", :name=>"Anita", :time=>2300, :count=>10, :hour=>"2", :avg=>2}, {:sid=>"101", :snumber=>"798798", :name=>"Anita 1", :time=>1800, :count=>32, :hour=>"", :avg=>1}, {:sid=>"160", :snumber=>"6546546", :name=>"Anita 22", :time=>1300, :count=>30, :hour=>"1", :avg=>1}]
或添加:desc以颠倒顺序:
array.sort_by_key(:name, :desc)
#=> [{:sid=>"160", :snumber=>"6546546", :name=>"Anita 22", :time=>1300, :count=>30, :hour=>"1", :avg=>1}, {:sid=>"101", :snumber=>"798798", :name=>"Anita 1", :time=>1800, :count=>32, :hour=>"", :avg=>1}, {:sid=>"120", :snumber=>"6546546", :name=>"Anita", :time=>2300, :count=>10, :hour=>"2", :avg=>2}]
我省略了对参数的任何错误处理。
编辑:这可能会失败,并且字符串代表数字:"1", "12", "2"
是String类对象的有序序列,但是期望值为"1", "2", "12"
。万一,最好的选择是https://stackoverflow.com/a/51215213/5239030