Beginner questions: sorting csv files

Hello,
I am a newbie with Ruby and I had a couple of questions while
manipulating csv files. How would I do a multiple column sort? I have
a file that needs to be sorted by the 3rd column, then 1st, then second.
I understand how to do one sort for the csv file but I was unsure of how
to do multiple.

Also,How would I to do a percentage change between two numbers in a
column?

Thank you very much. I know these are easy questions but I am still
learning how to program in Ruby.

On Feb 2, 10:52 am, Michael Sc [email protected] wrote:

Thank you very much. I know these are easy questions but I am still
learning how to program in Ruby.


Posted viahttp://www.ruby-forum.com/.

[ [9,‘ash’,‘cube’],
[8,‘blue’,‘cube’],
[3,‘mauve’,‘frustrum’],
[8,‘green’,‘cube’]
].sort_by{|a| a.values_at( 2,0,1 ) }.
each{|a| p a }

— output -----
[8, “blue”, “cube”]
[8, “green”, “cube”]
[9, “ash”, “cube”]
[3, “mauve”, “frustrum”]

Thank you very much. I did not realize it was so simple. Do you know
how to refer to prior lines to make calculations?

William J. wrote:

On Feb 2, 4:26 pm, Michael Sc [email protected] wrote:

Thank you very much. I did not realize it was so simple. Do you know
how to refer to prior lines to make calculations?


Posted viahttp://www.ruby-forum.com/.

a =
[ [‘alloy’, 1.414],
[‘malign’, 1.732],
[‘smudge’, 2.0],
[‘smack’, 2.236]
]

0.upto( a.size - 2 ) {|i|
puts “Change from line #{i} to line #{i+1}:
#{ (a[i+1][1] - a[i][1]) / a[i][1] * 100 }%”
}
Thank you very much. I just had one more question about this then. How
would I write this to its own csv file?

require ‘csv’
outfile = File.open(‘newfile.csv’, ‘wb’)
x=CSV.open(“oldfile.csv”, “r”)
x.sort_by{|a| a.values_at( 2,0,1 ) }.each{|a| outfile.print a }
outfile.close

I tried outfile.p(doesn’t work), outfile.print(takes out the commas) and
outfile.put(takes out the breaks). I know this should be incredibly
easy but I am clearly missing something.

On Feb 2, 9:53 pm, Michael Sc [email protected] wrote:

[‘malign’, 1.732],
would I write this to its own csv file?

require ‘csv’
outfile = File.open(‘newfile.csv’, ‘wb’)
x=CSV.open(“oldfile.csv”, “r”)
x.sort_by{|a| a.values_at( 2,0,1 ) }.each{|a| outfile.print a }
outfile.close

I tried outfile.p(doesn’t work), outfile.print(takes out the commas) and
outfile.put(takes out the breaks). I know this should be incredibly
easy but I am clearly missing something.

Before writing each record (i.e., each array of fields) to the file,
it must first be converted to a proper csv string.
The ‘csv’ package has a method for doing this, I presume.

If you don’t wan’t to use that, try this:

class Array
def to_csv
s = ‘’
map { |item|
str = item.to_s
# Quote the string if it contains the field-separator or
# a " or a newline or a carriage-return, or if it has leading or
# trailing whitespace.
if str.index( “,” ) or /^\s|[“\r\n]|\s$/.match(str)
str = '”’ + str.gsub( /“/, '”“’ ) + '”’
end
str
}.join( “,” )
end
end

puts [ 674, “yes”, “Jones,Tom”, ‘foo"bar’, " space " ].to_csv

— output -----
674,yes,“Jones,Tom”,“foo”“bar”," space "

Thank you very much.

On Feb 2, 4:26 pm, Michael Sc [email protected] wrote:

Thank you very much. I did not realize it was so simple. Do you know
how to refer to prior lines to make calculations?


Posted viahttp://www.ruby-forum.com/.

a =
[ [‘alloy’, 1.414],
[‘malign’, 1.732],
[‘smudge’, 2.0],
[‘smack’, 2.236]
]

0.upto( a.size - 2 ) {|i|
puts “Change from line #{i} to line #{i+1}:
#{ (a[i+1][1] - a[i][1]) / a[i][1] * 100 }%”
}

Hey,
I just had another question on these csv files. Is there anyway I could
save sorted files using the fastercsv library? Thanks again for all of
the help. I am having trouble figuring out how to use the libraries.

Michael Sc wrote:

Hey,
I just had another question on these csv files. Is there anyway I could
save sorted files using the fastercsv library? Thanks again for all of
the help. I am having trouble figuring out how to use the libraries.

Assuming your csv file is stored as “my_array”:

require ‘rubygems’
require ‘faster_csv’

FCSV.open(“output.csv”,“w”) do |out|
my_array.each{|row| out << row}
end

Michael Sc wrote:

Hello,
I am a newbie with Ruby and I had a couple of questions while
manipulating csv files. How would I do a multiple column sort? I have
a file that needs to be sorted by the 3rd column, then 1st, then second.
I understand how to do one sort for the csv file but I was unsure of how
to do multiple.

Also,How would I to do a percentage change between two numbers in a
column?

Thank you very much. I know these are easy questions but I am still
learning how to program in Ruby.

Come to think of it, I’d do the whole thing using FasterCSV. When
available, I like to use a well known library where the hard work has
already been done for me :slight_smile:

require ‘rubygems’
require ‘faster_csv’

mycsv = FCSV.read(“myfile.csv”)

FCSV.open(“output.csv”,“w”) do |out|
mycsv.sort{|a,b| [a[2],a[0],a[1]] <=> [b[2],b[0],b[1]]}.each |row|
out << row
end
end

Drew O. wrote:

Assuming your csv file is stored as “my_array”:

require ‘rubygems’
require ‘faster_csv’

FCSV.open(“output.csv”,“w”) do |out|
my_array.each{|row| out << row}
end
Thank you very much.

On Feb 6, 2007, at 9:51 AM, Drew O. wrote:

mycsv.sort{|a,b| [a[2],a[0],a[1]] <=> [b[2],b[0],b[1]]}.each |row|

mycsv.sort_by { |row| row.values_at(2, 0, 1) }.each do |row|

:wink:

James Edward G. II

On Feb 6, 2007, at 9:51 AM, Drew O. wrote:

mycsv.sort{|a,b| [a[2],a[0],a[1]] <=> [b[2],b[0],b[1]]}.each |row|

mycsv.sort_by { |row| row.values_at(2, 0, 1) }.each do |row|

:wink:

James Edward G. II
thanks
that’s great to know.

on the daily return, I wanted to define two if statements so that two
columns had to equal in order to do take the percantage change function.
Does anyone have any ideas on this?
I tried to do this. Thanks again for the help.

0.upto( a.size - 2 ) {|i|
(a[i][1]==a[i+1][1] and a[i][2]==a[i+1][2]) (a[i+1][3] - a[i][3]) /
a[i][3] * 100}

James G. wrote:

On Feb 6, 2007, at 9:51 AM, Drew O. wrote:

mycsv.sort{|a,b| [a[2],a[0],a[1]] <=> [b[2],b[0],b[1]]}.each |row|

mycsv.sort_by { |row| row.values_at(2, 0, 1) }.each do |row|

:wink:

James Edward G. II

Ahh, neat, good to know.

Michael Sc wrote:

on the daily return, I wanted to define two if statements so that two
columns had to equal in order to do take the percantage change function.
Does anyone have any ideas on this?
I tried to do this. Thanks again for the help.

0.upto( a.size - 2 ) {|i|
(a[i][1]==a[i+1][1] and a[i][2]==a[i+1][2]) (a[i+1][3] - a[i][3]) /
a[i][3] * 100}

Also, Does anyone have any recommendations about books that have a large
discussion of ruby for math purposes?

Michael Sc wrote:

Also, Does anyone have any recommendations about books that have a large
discussion of ruby for math purposes?

There is a SciRuby web site at

http://sciruby.codeforpeople.com/sr.cgi/FrontPage


M. Edward (Ed) Borasky, FBG, AB, PTA, PGS, MS, MNLP, NST, ACMC(P)
http://borasky-research.blogspot.com/

If God had meant for carrots to be eaten cooked, He would have given
rabbits fire.