我有一个数组:
["Melanie", "149", "Joe", "2", "16", "216", "Sarah"]
我想创建一个哈希:
{"Melanie"=>[149], "Joe"=>[2, 16, 216] "Sarah"=>nil}
当键和值在同一个数组中时,如何实现这一目标?
所有值都是整数(尽管它们在数组中是字符串形式。)所有键都以字母开头和结尾。
答案 0 :(得分:6)
您预期的哈希值无效。因此,你不可能得到你想要的东西。
从您的问题来看,期望值为数组似乎是合理的。在这种情况下,您可以这样做:
["Melanie", "149", "Joe", "2", "16", "216", "Sarah"]
.slice_before(/[a-z]/i).map{|k, *v| [k, v.map(&:to_i)]}.to_h
# => {"Melanie"=>[149], "Joe"=>[2, 16, 216], "Sarah"=>[]}
稍微修改一下,当数组长度为1时,可以让值为数字而不是数组,但这不是一个好的设计;它会引入例外。
答案 1 :(得分:2)
试试这个
def numeric?(x)
x.chars.all? { |y| ('0'..'9').include?(y) }
end
array = ["Melanie", "149", "Joe", "2", "16", "216", "Sarah"]
keys = array.select { |x| not numeric?(x) }
map = {}
keys.each do |k|
from = array.index(k) + 1
to = array.index( keys[keys.index(k) + 1] )
map[k] = to ? array[from...to] : array[from..from]
end
p map
<强>输出:强>
{"Melanie"=>["149"], "Joe"=>["2", "16", "216"], "Sarah"=>[]}
[Finished in 0.1s]
答案 2 :(得分:2)
这是另一种方式:
arr = ["Melanie", "149", "Joe", "2", "16", "216", "Sarah"]
class String
def integer?
!!(self =~ /^-?\d+$/)
end
end
Hash[*arr.each_with_object([]) { |s,a| s.integer? ? a[-1] << s.to_i : a<<s<<[] }].
tap { |h| h.each_key { |k| h[k] = nil if h[k].empty? } }
#=> {"Melanie"=>[149], "Joe"=>[2, 16, 216], "Sarah"=>nil}
答案 3 :(得分:1)
您的问题有三个组成部分,我将尝试单独回答。
关于存储多值映射,虽然有专门的解决方案可用,但最常见的建议是存储其值为数组的散列。也就是说,对于您的用例,您的主数据结构是一个哈希,其键是字符串,其值是整数数组。根据您所需的重复行为等,您可能希望用不同的数据结构替换值结构,可能是一组。
关于识别包含数字的字符串和不包含数字的字符串,那么,这取决于您的非数字字符串可能包含的确切内容,但一个好的起点是对数字执行正则表达式匹配。您没有指定允许的数字字符串是否表示整数,浮点数等。具体的答案可能会影响您的整体策略。不幸的是,在一般情况下,输入解析和验证是一个复杂而混乱的主题。
关于实际转换过程,我建议采用以下策略。迭代输入数组。检查每个字符串是否为数字或非数字。如果它是非数字的,则将其存储为本地的当前密钥。此外,在哈希中,创建从该键到新空数组的映射。相反,如果字符串是数字,则将其转换为数字,然后将其添加到相应键下的数组中。
答案 4 :(得分:0)
我不知道是否有一个很好的方法。我做这样的事情:
def numeric?(string)
# `!!` converts parsed number to `true`
!!Kernel.Float(string)
rescue TypeError, ArgumentError
false
end
def my_method(input_array)
# associate values with proper key and stores result in output
curr_key = nil
output = {}
input_array.each do |e|
if !numeric?(e)
output[e] = []
curr_key = e
else
# use Float if values may be floating-point
output[curr_key] << Integer(e, 10)
end
end
output.each do |k, v|
output[k] = v.empty? ? nil : v
end
output
end
numeric
方法的来源。