Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 根据另一个数组中的顺序对数组进行排序_Arrays_Ruby_Sorting - Fatal编程技术网

Arrays 根据另一个数组中的顺序对数组进行排序

Arrays 根据另一个数组中的顺序对数组进行排序,arrays,ruby,sorting,Arrays,Ruby,Sorting,我有一个数组: x = [ ["ready", 5], ["shipped", 1], ["pending", 1], ["refunded", 1], ["delivered", 23], ["scheduled", 1], ["canceled", 51] ] 我的排序数组是 order_array = [ "ready", "in_progress", "recieved", "shipped", "scheduled", "pick_up", "delivered", "

我有一个数组:

x = [
  ["ready", 5], ["shipped", 1], ["pending", 1], ["refunded", 1],
  ["delivered", 23], ["scheduled", 1], ["canceled", 51]
]
我的排序数组是

order_array = [
  "ready", "in_progress", "recieved", "shipped", "scheduled", "pick_up",
 "delivered", "canceled", "failed", "refunded", "refund_failed"
]
我需要根据每个子数组中第一个元素的值来排序
x
。所需的排序数组是:

[
  ["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23],
  ["canceled", 51], ["refunded", 1]
]
使用
sort\u by
不会产生所需的排序,它会导致相同的数组

result = x.sort_by {|u| order_array.index(u)}
# => [
#      ["ready", 5], ["shipped", 1], ["pending", 1], ["refunded", 1],
#      ["delivered", 23], ["scheduled", 1], ["canceled", 51]
# ]

您几乎做到了这一点:
index
在比较整个数组时不起作用,而不是它的第一个元素。这将有助于:

result = x.sort_by { |u| order_array.index(u[0]) || 100 }
#=> [["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23], ["canceled", 51], ["refunded", 1], ["pending", 1]]
请注意,
100
如果在
order\u数组
中找不到该值,则默认位于排序的后面


编辑

这一点最初被接受,尽管包括
[“待定”,1]
表明它符合要求;但是,这里有一个解决方案可以避免不需要的条目,如果需要,它还可以处理重复条目

order_array.each_with_object([]) { |ordered_by, array| array.push(*x.select { |item| item[0] == ordered_by }) }
#=> [["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23], ["canceled", 51], ["refunded", 1]]
或者,非常快,但仍允许在每个订购项下重复值:

hash = x.each_with_object(Hash.new { |h,k| h[k] = [] }) { |item, h| h[item[0]] << item[1] }
order_array.flat_map { |key| [key, hash[key]] }
hash=x.each_与_对象(hash.new{{h,k{h[k]=[]){item,h{h[item[0]]
或

我建议

x.keep_if { |e| order_array.include? e[0] }.sort_by { |e| order_array.index(e[0]) }
因为有些值不是
顺序数组的元素,例如
“pending”


到目前为止,对答案进行了基准测试
500次

#        user       system     total       real
# sawa   0.006698   0.000132   0.006830 (  0.006996) # on the first method
# ray    0.005543   0.000123   0.005666 (  0.005770)
# igian  0.001923   0.000003   0.001926 (  0.001927)
# srack  0.005270   0.000168   0.005438 (  0.005540) # on the last method

为了好玩,我尝试为Ruby 2.5找到一种更快的方法:

xx = x.to_h # less than Ruby 2.6
order_array.each.with_object([]) { |k, res| res << [k, xx[k]] if xx.has_key? k }
xx=x.to#h小于Ruby 2.6

order_array.each.with_object([]){k,res | res您可以尝试以下代码来高效地查找输出

order_array.map { |p| x.detect { |y| y[0] == p } }.compact
# => [["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23], ["canceled", 51], ["refunded", 1]]
似乎很有用:“搜索一个数组,该数组的元素也是数组,使用obj将obj与每个包含数组的第一个元素进行比较。”

我假设:

  • x
    的每个元素的第一个元素不一定是唯一的
  • x
    的所有元素,其第一个元素相同且其第一个元素是
    order\u数组的成员,在返回(排序)数组中按这些元素在
    x
    中出现的顺序连续出现
  • 如果
    x
    的任何元素的第一个元素不是
    order\u数组的成员,则在其第一个元素位于
    sorted\u数组中的所有元素之后,返回的(排序的)数组中会出现
    x
    中的所有元素,并且所有这些元素都会按照它们在
    x
    中出现的顺序出现在返回的数组中(末尾);以及
  • 效率是最重要的


必须初始化
order\u pos
,才能按
order\u arr
对其密钥进行排序。这是Ruby 1.9中一个有争议的更改的价值示例,该更改保证哈希键将保持密钥插入顺序。

这并没有给出OP想要的。可以看到它包括
挂起的
,w@sawa上面缺少我没有注意到的内容。如果这是必要的,你的方法更有意义。欢迎评论。你真正想要的输出是什么?我认为这符合OP的问题?输出被添加到我的答案中:它与所需的输出相匹配,尽管是
[“pending”,1]
撞到了阵列的背面。正如您所注意到的,
[“待定”,1]
被添加到了末尾,而OP并不想要(根据问题)。谢谢,这很有效,但@SRack解决方案非常简单。@Stefan是的。我隐式地认为是这样的。这些都不是重复的。第二个解决方案也很完美!很好,我不知道2.6在_h
中添加了一个
的块变量。这使我的上述注释无效。@Stefan这是根据我的要求。当我意识到我的错误时,我认为这是对我的编辑错误,虽然比@sawa的答案更复杂,所以觉得不值得。但仍然可读。我发现它循环了2次(增加了复杂性)而且,对于大型数组,
索引
的速度非常慢。@ray,实际上基准测试让我很惊讶。也许你可以再检查一下吗?我认为对于te OP的情况,数组很小。@iGian值得称赞-这确实比ray和我的第二个答案都好,即使它可以扩展。我已经用一个更大的数据集()基本上可以得出萨瓦是国王的结论:)那么
[“pending”,1]
-是否应该删除它,因为
“pending”
不是
顺序数组的元素
?RE
顺序数组[2]
:在“E”之前唱“I”,除非在“C”之后,或者在“neighbor”或“weight”中听起来像“A”(存在例外情况)以前从未见过也没听说过assoc-+1,因为它将它带入了我的生活:)回答得很好。你知道散列更快:)
#=> [["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23], ["canceled", 51], ["refunded", 1]]
#        user       system     total       real
# sawa   0.006698   0.000132   0.006830 (  0.006996) # on the first method
# ray    0.005543   0.000123   0.005666 (  0.005770)
# igian  0.001923   0.000003   0.001926 (  0.001927)
# srack  0.005270   0.000168   0.005438 (  0.005540) # on the last method
xx = x.to_h # less than Ruby 2.6
order_array.each.with_object([]) { |k, res| res << [k, xx[k]] if xx.has_key? k }
order_array.map { |p| x.detect { |y| y[0] == p } }.compact
# => [["ready", 5], ["shipped", 1], ["scheduled", 1], ["delivered", 23], ["canceled", 51], ["refunded", 1]]
order_array.map{|e| x.assoc(e) }.compact
x = [
  ["ready", 5], ["shipped", 1], ["pending", 1], ["refunded", 1], ["originated", 3],
  ["delivered", 23], ["scheduled", 1], ["ready", 8], ["canceled", 51]
]

order_array = [
  "ready", "in_progress", "received", "shipped", "scheduled", "pick_up",
  "delivered", "canceled", "failed", "refunded", "refund_failed"
]
order_pos = order_array.each_with_object({}) { |word,h| h[word] = [] }
  #=> {"ready"=>[], "in_progress"=>[], "received"=>[], "shipped"=>[],
  #    "scheduled"=>[], "pick_up"=>[], "delivered"=>[], "canceled"=>[],
  #    "failed"=>[], "refunded"=>[], "refund_failed"=>[]} 
back = x.each_with_index.with_object([]) { |((word,v),i),back|
  order_pos.key?(word) ? (order_pos[word] << i) : back << [word,v] }
  #=> [["pending", 1], ["originated", 3]] 
order_pos.flat_map { |word,offsets| offsets.map { |i| x[i] } }.concat(back)
  #=> [["ready", 5], ["ready", 8], ["shipped", 1], ["scheduled", 1],
  #    ["delivered", 23], ["canceled", 51], ["refunded", 1], ["pending", 1],
  #    ["originated", 3]] 
order_pos
  #=> {"ready"=>[0, 7], "in_progress"=>[], "received"=>[], "shipped"=>[1],
  #    "scheduled"=>[6], "pick_up"==>[], "delivered"=>[5], "canceled"=>[8],
  #    "failed"=>[], "refunded"=>[3], "refund_failed"=>[]}