["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
# 需要转换为
[["0.0", "0.1", "0.2"], [ "1.2", "1.3"], ["2.2", "2.3"], ["3.2"], ["4.0", "4.2"]]
就是根据数组中的元素,把它 split(".")
成为一个数组之后,如果数组的第一项相同,就把这个元素放到这样一个数组里面 ["0.0", "0.1", "0.2"]
比如说 "0.0", "0.1", "0.2"
分割后第一项都相同,就把它们放在一起
求一种简洁、高端、大气、上档次的转换方法~
能描述一下需求么?只看这个输入输出的话,我觉得可以这样
a = ["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
output = [
a[0..2],
a[3..4],
a[5..6],
a[7..7],
a[8..9],
]
假如需求是"按照每个元素的整数位分组", 那么可以这样
a = ["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
grouped = a.group_by {|n| n.to_i.round}
output = grouped.values_at(*grouped.keys.sort) # => 应该就是你需要的.
不过话说回来,直接拿 grouped
这个 hash 去用可能更方便?而且,假如说输入的数据中没有 1.x 的数,那么这个方法的输出可能会有问题。总之还是希望 LZ 完整严密地描述一下需求。否则我觉得还是前一个办法更好
@5long 谢谢你的回答
其实就是根据数组中的元素,把它split(".")
成为一个数组之后,如果数组的第一项相同,就把这个元素放到这样一个数组里面["0.0", "0.1", "0.2"]
比如说"0.0", "0.1", "0.2"
分割后第一项都相同,就把它们放在一起
["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"].group_by{|s| s[0]}.values
data = ["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2"]
data.group_by(&:to_i).values
["0.0", "0.1", "0.2", "1.2", "1.3", "2.2", "2.3", "3.2", "4.0", "4.2", "11.1", "11.2"].group_by{|s| s.to_i}.values
如果需要保序,就用 chunk
例如
["0.0", "0.1", "1.2", "1.3", "0.2"].chunk(&:to_i).map &:last
#=> [["0.0", "0.1"], ["1.2", "1.3"], ["0.2"]] 最后的 0.2 不合并到第一项中去
#1 楼 @5long #4 楼 @jjym #6 楼 @zgm #7 楼 @quakewang #8 楼 @wuwx #10 楼 @luikore #11 楼 @sevk
忍不住 at 了楼上所有人的原因是,你们真的觉得在这个问题里面用上了 :to_i 这个方法是合适的吗??
看到楼上的朋友用 :to_i,让我想起了大一上 C 语言课的时候,老师要我们计算一个数字有几个尾随的 0,比如 300 有两个,10000 有四个。由于 C 语言里面的字符串老师不打算让我们接触,于是就让我们通过求余的思维来做这一题,而且它也没提到 其实这题就逻辑上来说,是不应该用求余来做的 。
楼上的各位你们想想,楼主的需求要的是一种 模式 上的匹配!而你们却通过 :to_i 的方式来找出这种模式上的匹配,我觉得是不可取的一种思维。更正确的方式应该是通过字符串的思维来对待楼主的需求,即,通过正则来完成。
借用一下 #11 楼 的代码,我给出的答案是:
["11.0", "0.1", "1.2", "1.3", "0.2", "-11.5"].group_by{|s| s.match(/(.+?)./)[1] }
输出:
{"11"=>["11.0"], "0"=>["0.1", "0.2"], "1"=>["1.2", "1.3"], "-11"=>["-11.5"]}
果然自己的代码写得有点冗余~ .to_i 本身就已经转换成整数了,再 .round 没有意义。只调用 .to_i 的话就可以像 #7 楼 那样利用 &to_i 的语法了。
其实看了 #2 楼 的描述,我依然不能确定 lz 的原始需求是什么。如果能确定输入数据肯定都是干净的浮点数(只是暂时存成字符串),那么按 .to_i 的结果分组应该肯定是够用的。以及,如果数据是稀疏的,比如缺少 1.x 的输入,那么在输出的数组里原本属于 1.x 的位置上应该是 nil, 还是空数组,都只能看具体需求。
#12 楼 @alsotang 既然你用了正则,那么我也引用一下自己学习正则的知识。这本书教会我的一个重要理念是:先熟悉你手头的数据,正则写得足够好即可,十分严谨的、面面俱到的 parser 用一个巨大的正则来做非常的痛苦。像 LZ 这个问题,如果已知数据都是存成了字符串的浮点数,确定有“浮点数”这个语义在的话,用 .to_i 我觉得非常合适。但如果真如 #2 楼 所言,每个元素只是“中间恰好有一个 .
的字符串”,那么用正则确实更合适。在背景信息完整之前,我觉得没法断言哪个方案更正确。我们写代码都是想解决问题,而不是为了让自己的答案反映出自己学会了课本上的知识点。
依然,如果原始需求不明,数据来源不确定,output = [ a[0..2], a[3..4], ... ]
这个答案我觉得也未必不可。但是在社区里扔下这么一个答案就跑给人太 trolling 的感觉,所以我没敢这么做。
咋没人想着 split 呢?效率?
[.....].group_by { |n| n.split('.')[0] }
反正是方便,避免 match 不匹配@neverlandxy_naix @luikore