【问题标题】:Print array values based in sorting list and ascending order根据排序列表和升序打印数组值
【发布时间】:2017-12-25 07:50:28
【问题描述】:

请您帮忙。我有想要按 2 个条件排序的数组“值”。

第一个条件:使用数组“sortlist”中定义的排序列表。 第二个条件:从小到大。

使用我当前的脚本,我已经能够以正确的顺序打印第一个条件(排序列表)的值,但我不知道如何应用第二个排序条件(从最小到最大)。

ruby -e'
values = [ "Ghu_1","Prw_1","Prw_3","Prw_5","Vep_3","Hom_2","Vep_1","Hom_1","Prw_2","Vep_2","Prw_4" ]
sortlist = [ "Hom","Vep","Ghu","Prw" ]

sortlist.each{ |s| 
 values.each{ |v| 
     puts v if v.include?(s)
 }
}'




Current Ouput  #  Desired output
   Hom_2       #      Hom_1
   Hom_1       #      Hom_2
   Vep_3       #      Vep_1
   Vep_1       #      Vep_2
   Vep_2       #      Vep_3
   Ghu_1       #      Ghu_1
   Prw_1       #      Prw_1
   Prw_3       #      Prw_2
   Prw_5       #      Prw_3
   Prw_2       #      Prw_4
   Prw_4       #      Prw_5

更新

感谢塞巴斯蒂安。优秀。

它几乎可以工作,因为我注意到如果“_”之后的字符不是数字,那么第二个排序是不正确的。例如下面的输出对于 Pwr_XXX 的值是不正确的

 ruby -e'
 values = [ "Ghu_Klca","Prw_Rkdg","Prw_Ceteu","Prw_Eriir","Vep_Msas23","Hom_Ttgr5","Vep_Qsccas","Hom_Ftjh","Prw_jpolq","Vep_Szbqh","Prw_Lmnajh" ]
 sortlist = [ "Hom","Vep","Ghu","Prw" ]

 puts sortlist.flat_map{ |s|
   values.select{ |v|
     v if v.include?(s)
   }.sort
 }'

第二次更新

我的意思是第一个排序是基于 sortlist 数组。第二种排序是基于“_”之后的字符升序。在这种情况下,Prw 值的第一个字母是 C、E、j、L 和 R。但当前输出为 C、E、L、R 和 j。所以,j 在最后,应该在 L 之后。我希望有意义。

Current output        Expected output
Hom_Ftjh          #      Hom_Ftjh 
Hom_Ttgr5         #      Hom_Ttgr5 
Vep_Msas23        #      Vep_Msas23 
Vep_Qsccas        #      Vep_Qsccas 
Vep_Szbqh         #      Vep_Szbqh 
Ghu_Klca          #      Ghu_Klca 
Prw_Ceteu         #      Prw_Ceteu 
Prw_Eriir         #      Prw_Eriir 
Prw_Lmnajh        #      Prw_jpolq 
Prw_Rkdg          #      Prw_Lmnajh 
Prw_jpolq         #      Prw_Rkdg

【问题讨论】:

  • 第二次排序不正确是什么意思?预期的输出是多少?
  • 请看我的第二次更新。谢谢

标签: arrays ruby sorting multiple-conditions


【解决方案1】:

查看您的代码,您可以做的是创建一个空数组,然后在您的 values.each 迭代中,如果该元素包含来自 sortlist 的元素,则将每个元素推送到您的空数组中

new_list = []
sortlist.each{ |s|
  values.each{ |v|
    new_list << v if v.include?(s)
  }
}

然后使用group_by按第一个字符分组:

p new_list.group_by{|e| e[0]}
# => {"H"=>["Hom_2", "Hom_1"], "V"=>["Vep_3", "Vep_1", "Vep_2"], "G"=>["Ghu_1"], "P"=>["Prw_1", "Prw_3", "Prw_5", "Prw_2", "Prw_4"]}

然后使用flat_map 得到一个包含所有值的“普通”数组,但在迭代内部对散列中每个键的每个值进行排序:

p new_list.group_by{|e| e[0]}.flat_map{|_,v| v.sort}
# => ["Hom_1", "Hom_2", "Vep_1", "Vep_2", "Vep_3", "Ghu_1", "Prw_1", "Prw_2", "Prw_3", "Prw_4", "Prw_5"]

flat_mapselectsort_by 组合(第二次更新):

values = [ "Ghu_Klca","Prw_Rkdg","Prw_Ceteu","Prw_Eriir","Vep_Msas23","Hom_Ttgr5","Vep_Qsccas","Hom_Ftjh","Prw_jpolq","Vep_Szbqh","Prw_Lmnajh" ]
sortlist = [ "Hom","Vep","Ghu","Prw" ]

p sortlist.flat_map{ |s|
  values.select{ |v|
    v if v.include?(s)
  }.sort_by(&:downcase)
}
# => ["Hom_Ftjh", "Hom_Ttgr5", "Vep_Msas23", "Vep_Qsccas", "Vep_Szbqh", "Ghu_Klca", "Prw_Ceteu", "Prw_Eriir", "Prw_jpolq", "Prw_Lmnajh", "Prw_Rkdg"]

排序时使用sort_by(&amp;:downcase)“忽略”大小写。

【讨论】:

  • 完全按照我的要求工作。您的第二次更新甚至对数值进行排序! Muchas Gracias Sebastián。
【解决方案2】:
values.sort_by { |val|
  front, back = val.split('_')
  [sortlist.index(front), back.downcase]
}
# => ["Hom_1", "Hom_2", "Vep_1", "Vep_2", "Vep_3", "Ghu_1", "Prw_1", "Prw_2", "Prw_3", "Prw_4", "Prw_5"]
# or
# => ["Hom_Ftjh", "Hom_Ttgr5", "Vep_Msas23", "Vep_Qsccas", "Vep_Szbqh", "Ghu_Klca", "Prw_Ceteu", "Prw_Eriir", "Prw_Lmnajh", "Prw_Rkdg", "Prw_jpolq"]

这是有效的,因为数组通过比较第一个元素进行比较,如果前一个元素相等,则比较下一个元素。目前我正在比较back,就好像它是一个字符串(102 之前);如果您想要数字排序(210 之前),请使用back.to_iback.to_f(但这不适用于第二个示例)。

【讨论】:

  • 感谢 Amadan 的解释。您知道如何固定每组相似值中的排序吗?我称之为第二种。
  • 根据您的说明,您需要不区分大小写的排序。这可以通过排序标准中的downcase 来完成。答案相应地改变了。
  • 非常感谢阿马丹。它适用于您更新的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多