我有一个如下所示的数组:
["mac1", "mac2", "mac3", "win1", "win2", "win3", "tablet1", "tablet2", "tablet3", "tablet5"]
如何将具有相似名称的值分组到这样的范围内?
["mac1-3", "win1-3", "tablet1-3", "tablet5"]
请注意,这些数字并不总是连续的(请查看"数位板"值)
答案 0 :(得分:1)
假设这些数字是连续的:
["mac1", "mac2", "mac3", "win1", "win2", "win3"]
.group_by{|e| e[/\D+/]}
.map{|k, v| k + v.map{|s| s[/\d+/].to_i}.minmax.join("-")}
# => ["mac1-3", "win1-3"]
答案 1 :(得分:1)
这是一种方法。
<强>代码强>
def group_em(arr)
arr.map { |w| [w[/[a-z]+/i], w[/\d+/].to_i] }
.sort
.slice_when { |(e1,n1),(e2,n2)| (e1 != e2) || n2 > n1+1 }
.map do |arr|
s = "#{arr.first.first}#{arr.first.last}"
(arr.size>1) ? (s << "-#{arr.last.last}") : s
end
end
示例强>
arr = ["tablet2", "win2", "tablet3", "win1", "win3", "mac1",
"tablet99", "mac3", "mac2", "tablet1"]
group_em(arr)
#=> ["mac1-3", "tablet1-3", "tablet99", "win1-3"]
<强>解释强>
a = arr.map { |w| [w[/[a-z]+/i], w[/\d+/].to_i] }.sort
#=> [["mac", 1], ["mac", 2], ["mac", 3], ["tablet", 1], ["tablet", 2],
# ["tablet", 3], ["tablet", 99], ["win", 1], ["win", 2], ["win", 3]]
使用Enumerable#slice_when(在第2.2节中介绍)切片:
e = a.slice_when { |(e1,n1),(e2,n2)| (e1 != e2) || n2 > n1+1 }
#=> #<Enumerator: #<Enumerator::Generator:0x007ffb1c8547a0>:each>
我们可以通过将它转换为数组来查看此枚举器的元素:
e.to_a
#=> [[["mac", 1], ["mac", 2], ["mac", 3]],
# [["tablet", 1], ["tablet", 2], ["tablet", 3]],
# [["tablet", 99]],
# [["win", 1], ["win", 2], ["win", 3]]]
最后:
e.map do |arr|
s = "#{arr.first.first}#{arr.first.last}"
(arr.size>1) ? (s << "-#{arr.last.last}") : s
end
#=> ["mac1-3", "tablet1-3", "tablet99", "win1-3"]
答案 2 :(得分:0)
假设数字之间没有中断(即如果我们有值1和3则存在2)
input = ["mac1", "mac2", "mac3", "win1", "win2", "win3"]
h = input.each_with_object({}) do |i, h|
m = i.match(/(.*?)(\d+)/)
fst = m[1]
snd = m[2].to_i
h[fst] = [] if h[fst].nil?
h[fst] << snd
end
output = h.each_with_object([]) do |(k, v), a|
a << "#{k}#{v.min}-#{v.max}"
end
puts output # outputs ["mac1-3", "win1-3"]