2014-04-17 57 views
2

我希望能够将文件读取到关联数组中,我可以通过列头名称访问元素。将文件读入关联数组

我的文件的格式如下:

 
KeyName Val1Name Val2Name ... ValMName 
Key1  Val1-1  Val2-1 ... ValM-1 
Key2  Val1-2  Val2-2 ... ValM-2 
Key3  Val1-3  Val2-3 ... ValM-3 
..   ..   ..  .. .. 
KeyN  Val1-N  Val2-N ... ValM-N 

唯一的问题是我没有线索如何做到这一点做。到目前为止,我有:

scores = File.read("scores.txt") 
lines = scores.split("\n") 
lines.each { |x| 
    y = x.to_s.split(' ') 
} 

哪些接近我想要的,但仍然无法使它成为可用于我的格式。

+0

是由制表符或一定数量的空格分隔的列? – bjhaid

+0

他们看起来像只是无限数量的空间。绝对不是标签。 – Brianne

回答

0

可在3线来完成(这就是为什么我喜欢红宝石)

scores = File.readlines('/scripts/test.txt').map{|l| l.split(/\s+/)} 
headers = scores.shift 
scores.map!{|score|Hash[headers.zip(score)]} 

现在scores包含您的散列阵列

这里是一个详细的解释

#open the file and read 
#then split on new line 
#then create an array of each line by splitting on space and stripping additional whitespace 
scores = File.open('scores.txt', &:read).split("\n").map{|l| l.split(" ").map(&:strip)} 
#shift the array to capture the header row 
headers = scores.shift 
#initialize an Array to hold the score hashs 
scores_hash_array = [] 
#loop through each line 
scores.each do |score| 
    #map the header value based on index with the line value 
    scores_hash_array << Hash[score.map.with_index{|l,i| [headers[i],l]}] 
end 
#=>[{"KeyName"=>"Key1", "Val1Name"=>"Val1-1", "Val2Name"=>"Val2-1", "..."=>"...", "ValMName"=>"ValM-1"}, 
    {"KeyName"=>"Key2", "Val1Name"=>"Val1-2", "Val2Name"=>"Val2-2", "..."=>"...", "ValMName"=>"ValM-2"}, 
    {"KeyName"=>"Key3", "Val1Name"=>"Val1-3", "Val2Name"=>"Val2-3", "..."=>"...", "ValMName"=>"ValM-3"}, 
    {"KeyName"=>"..", "Val1Name"=>"..", "Val2Name"=>"..", "..."=>"..", "ValMName"=>".."}, 
    {"KeyName"=>"KeyN", "Val1Name"=>"Val1-N", "Val2Name"=>"Val2-N", "..."=>"...", "ValMName"=>"ValM-N"}] 

scores_hash_array现在已经在表的每一行的哈希值。

+0

这是一个很好的答案,非常感谢! 现在我将如何使用scores_hash_array中的值作为对象的初始化值? IE obj = obj.new(key1,val1-1,val2-1,val3-1 ... valN-1) 然后根据密钥散列这些对象。记住我完全用C语言的心态来做这件事。 – Brianne

1
f = File.open("scores.txt") #get an instance of the file 
first_line = f.gets.chomp #get the first line in the file (header) 
first_line_array = first_line.split(/\s+/) #split the first line in the file via whitespace(s) 
array_of_hash_maps = f.readlines.map do |line| 
         Hash[first_line_array.zip(line.split(/\s+/))] 
        end 
#read the remaining lines of the file via `IO#readlines` into an array, split each read line by whitespace(s) into an array, and zip the first line with them, then convert it into a `Hash` object, and return a collection of the `Hash` objects 
f.close #close the file 

puts array_of_hash_maps #print the collection of the Hash objects to stdout 
+0

这正是我所需要的,非常感谢。 Ruby与我所做过的每件事都截然不同。 :) – Brianne

+1

无需保持文件打开你可以使用'File.readlines'直接读取整个数组到数组中# – engineersmnky

+0

@engineersmnky你需要第一行使用一个键,这就是'first_line = f.gets.chomp'并且剩下的行 – bjhaid

0

你可以尝试这样的事情: -

enter code here 
fh = File.open("scores.txt","r") 
rh={} #result Hash 
fh.readlines.each{|line| 
kv=line.split(/\s+/) 
puts kv.length 
rh[kv[0]] = kv[1..kv.length-1].join(",") #***store the values joined by "," 
} 
puts rh.inspect 
fh.close 

如果你想获得值的数组,通过 RH [KV [0] = KV [替换循环的最后一行1..kv.length-1]

+0

这有助于很多!非常感谢! :) – Brianne