From: roktas Date: 2002-02-24T09:32:59+09:00 Subject: Re: Newbie question Hi, David and Alan (Chen), thanks for your quick replies. Let me first clarify a point that this is not a real-world problem for me (otherwise David's post would be enough.) I just want to tinker with some concepts and also to realize an elegantly simple, effective solution in terms of OOP principles. > > What you want, I think, is an array of hashes. Each hash would > represent one line from your data file. > Actually, this is the first approach I tried. But, with keys of hash object, there would be 2*n records for n (equal) lines. So, I've come to the following point (please do not care for lexical errors) $FMT = "/\t/" # Only one hash for the field labels (not 2*n) $labels = {} def parse_line(line, fmt=$FMT) # No extra process for the present line.chomp.strip(delim) end def DB def initialize(f) # First create the $labels hash from the first line $labels = ... # Other stuff filling the @tab array ... end ... def [](key) @tab[key] end end def Record < Array def initialize(line) # Parse and create a new record parse_line(line) end def [](key) key if key.kind_of?Integer $labels.index(key) if key.kind_of?String # Raise something for invalid cases ? end end Well... (1) I don't want to use any global var ($labels), (2) Seperating 'records' and 'whole database' (DB) would be fine. > Here's a little example, data file first then program file. It first > grabs the first line from the file, and gets the field names from it. > Then it reads the other lines; for each one, it creates a hash (with > the field names as keys and the values from the line as values), and > pushes that hash onto the TSDB object itself. > > # tsd.txt (tab-separated): > field1 field2 field3 > one two three > apple orange banana > > # tsd.rb: > class TSDB < Array > > def initialize(file) > concat ["Dummy 0'th element"] # so that you can index from 1 > fh = File.open(file, "r") > fields = fh.readline.chomp.split(/\t/) > > fh.readlines.each do |line| > data = line.chomp.split(/\t/) > record = {} > fields.each_with_index {|f,i| record[f] = data[i]} > push(record) > end > end > end > > t = TSDB.new("tsd.txt") > p t[1]["field1"] # => "one" > p t[2]["field2"] # => "orange" > > __END__ > > > Since t[1] is a hash, you can get at its values with strings (i.e., its > keys are strings). > Nice piece of code :) Short and readable... Thanks again. -- roktas