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ā€]

1 Like

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§
http://borasky-research.blogspot.com/

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