简体   繁体   中英

need help printing contents of a ruby hash into a table

I have a file that contains this:

PQRParrot, Quagga, Raccoon
DEFDo statements, Else statements, For statements
GHIGeese, Hippos, If statements
YZ Yak, Zebra
JKLJelly Fish, Kudu, Lynx
MNOManatee, Nautilus, Octopus
ABCApples, Boas, Cats
VWXVulture, While statements, Xmen
STUSea Horse, Tapir, Unicorn

I need to display it in a table like this:

Key Data
ABC Apples, Boas, Cats
DEF Do statements, Else statements, For statements
GHI Geese, Hippos, If statements
JKL Jelly Fish, Kudu, Lynx
MNO Manatee, Nautilus, Octopus
PQR Parrot, Quagga, Raccoon
STU Sea Horse, Tapir, Unicorn
VWX Vulture, While statements, Xmen
YZ Yak, Zebra

Here is the code that I have so far:

lines = File.open("file.txt").read.split
fHash = {}
lines.each do |line|
  next if line == ""
  fHash[line[0..2]] = line[3..-1]
end

f = File.open("file.txt")
fHash = {}
loop do
  x = f.gets
  break unless x
  fHash[x[0..2]] = x[3..-1]
end

fHash = fHash.to_a.sort.to_h

puts fHash

f.close

And this is what the code outputs:

{ "ABC" => "Apples, Boas, Cats\n",
  "DEF" => "Do statements, Else statements, For statements\n",
  "GHI" => "Geese, Hippos, If statements\n",
  "JKL" => "Jelly Fish, Kudu, Lynx\n",
  "MNO" => "Manatee, Nautilus, Octopus\n",
  "PQR" => "Parrot, Quagga, Raccoon\n",
  "STU" => "Sea Horse, Tapir, Unicorn\n", 
  "VWX" => "Vulture, While statements, Xmen\n",
  "YZ " => "Yak, Zebra\n"
}

So what i'm trying to do is read the contents of the file, take the first three characters and set it as the key while the rest as data, sort the hash by the key value, then display the data as a table.

I have looked around, found a few things similar to my issue but nothing worked out for me.

I think you're overthinking this. If you have a file with those contents, to print the table all you need to do is insert a space after the third character of each line and then sort them (or the other way around). That's pretty simple:

lines = File.foreach("homework02.txt")
          .map {|line| line.insert(3, " ") }

puts "Key Data"
puts lines.sort

If instead you want to build a Hash from the lines of the file, all you have to do is this:

hsh = File.foreach("homework02.txt")
        .map {|line| [ line.slice!(0,3), line ] }
        .sort.to_h

This builds an array of two-element arrays whose first element is the first three characters of each line and whose second is the rest of the line, then sorts it and turns it into a hash.

Then, to print your table:

puts "Key Data"
puts hsh.map {|key, val| "#{key} #{val}" }

I got it to work by changing the way it sorts. Updated code below.

lines = File.open("homework02.txt").read.split
fHash = {}
lines.each do |line|
  next if line == ""
  fHash[line[0..2]] = line[3..-1]
end

f = File.open("homework02.txt")
fHash = {}
loop do
  x = f.gets
  break unless x
  fHash[x[0..2]] = x[3..-1]
end

fHash = Hash[fHash.sort_by { |k, v| k }]

print "Key ", " Data \n"

fHash.each do |key, val|
print key, " ", val
end

f.close

I have assumed that every line begins with one or more capital letters, followed by an optional space, followed by a capital letter, followed by a lowercase letter.

Code

R = /
    \A[A-Z]+       # Match start of string followed by one or more capital letters
    \K             # Forget everything matched so far
    (?=[A-Z][a-z]) # Match a capital letter followed by a lowercase letter
                   # in a postive lookahead
    /x             # Extended/free-spacing regex definition mode

Read the file, line by line, format each line, partition each line on the first space and sort:

def make_string(fname)
  File.foreach(fname).map { |s| s.gsub(R, ' ').chomp.partition(' ') }.
       sort.
       map(&:join)
end

If you instead wish to create the specified hash, you could write:

def make_hash(fname)
  File.foreach(fname).map { |s| s.gsub(R, ' ').chomp.partition(' ') }.
     sort.
     map { |f,_,l| [f,l] }.
     to_h
end

In the regex the first part of the string cannot be matched in a positive lookbehind because the match is variable-length. That's why I used \\K , which does not have that limitation.

Examples

First, let's create the file:

str = <<_
PQRParrot, Quagga, Raccoon
DEFDo statements, Else statements, For statements
GHIGeese, Hippos, If statements
YZ Yak, Zebra
JKLJelly Fish, Kudu, Lynx
MNOManatee, Nautilus, Octopus
ABCApples, Boas, Cats
VWXVulture, While statements, Xmen
STUSea Horse, Tapir, Unicorn
_

FName = 'temp'
File.write(FName, str)
  #=> 265 

Then

puts make_string(FName)
ABC Apples, Boas, Cats
DEF Do statements, Else statements, For statements
GHI Geese, Hippos, If statements
JKL Jelly Fish, Kudu, Lynx
MNO Manatee, Nautilus, Octopus
PQR Parrot, Quagga, Raccoon
STU Sea Horse, Tapir, Unicorn
VWX Vulture, While statements, Xmen
YZ Yak, Zebra

make_hash(FName)
  #=> {"ABC"=>"Apples, Boas, Cats",
  #    "DEF"=>"Do statements, Else statements, For statements",
  #    "GHI"=>"Geese, Hippos, If statements",
  #    "JKL"=>"Jelly Fish, Kudu, Lynx",
  #    "MNO"=>"Manatee, Nautilus, Octopus",
  #    "PQR"=>"Parrot, Quagga, Raccoon",
  #    "STU"=>"Sea Horse, Tapir, Unicorn",
  #    "VWX"=>"Vulture, While statements, Xmen",
  #    "YZ"=>"Yak, Zebra"} 

As a second example, suppose:

str = <<_
PQRSTUVParrot, Quagga, Raccoon
DEFDo statements, Else statements, For statements
Y Yak, Zebra
_

FName = 'temp'
File.write(FName, str)
  #=> 94

Then

puts make_string(FName)
PQRSTUV Parrot, Quagga, Raccoon
Y Yak, Zebra

make_hash(FName)
  # => {"DEF"=>"Do statements, Else statements, For statements",
  #     "PQRSTUV"=>"Parrot, Quagga, Raccoon", "Y"=>"Yak, Zebra"} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM