3

Stock data.csv

1425904377,22532.1309,22533.6992,22524.0703,22524.0703,0
1425904438,22533.4395,22533.4395,22529.2793,22532.2207,0
1425904499,22531.8809,22536.0801,22531.8809,22533.2793,0
1425904559,22532.4297,22534.7207,22530.7598,22532.0996,0
1425904618,22535.7695,22535.9297,22530.6094,22532.2500,0
1425904679,22536.0703,22539.2598,22535.5605,22535.6094,0
1425904738,22542.8809,22544.2305,22536.3594,22536.3594,0
1425904797,22540.6504,22544.0391,22538.5000,22542.9707,0
1425904857,22545.2891,22552.5098,22538.5898,22538.9004,0
1425904860,22547.0703,22547.0703,22547.0703,22547.0703,0

I have to do two things:

  1. Sort row by timestamp (first value)
  2. Delete duplicate (key: timestamp)

I tried this, but it isn't working:

my_csv = CSV.read("public/#{symbol}.csv")
my_csv.sort_by!(&:first)


open("public/#{symbol}.csv", 'w') { |f|
  my_csv.each do |row|
    f.puts "#{row.join(",")}"
  end
}
sparkle
  • 7,530
  • 22
  • 69
  • 131

1 Answers1

6
require 'csv'
my_csv = CSV.read 'data.csv'

my_csv.sort! { |a, b| a[0].to_i <=> b[0].to_i }
my_csv.uniq!(&:first)

my_csv.each { |line| p line }

Output:

["1425904377", "22532.1309", "22533.6992", "22524.0703", "22524.0703", "0"]
["1425904438", "22533.4395", "22533.4395", "22529.2793", "22532.2207", "0"]
["1425904499", "22531.8809", "22536.0801", "22531.8809", "22533.2793", "0"]
["1425904559", "22532.4297", "22534.7207", "22530.7598", "22532.0996", "0"]
["1425904618", "22535.7695", "22535.9297", "22530.6094", "22532.2500", "0"]
["1425904679", "22536.0703", "22539.2598", "22535.5605", "22535.6094", "0"]
["1425904738", "22542.8809", "22544.2305", "22536.3594", "22536.3594", "0"]
["1425904797", "22540.6504", "22544.0391", "22538.5000", "22542.9707", "0"]
["1425904857", "22545.2891", "22552.5098", "22538.5898", "22538.9004", "0"]
["1425904860", "22547.0703", "22547.0703", "22547.0703", "22547.0703", "0"]
  • CSV.read will read the file as an Array
  • We can use sort with a callback, in the callback we get 2 items to compare
  • We compare the first item (the timestamp), we convert it to integer, to make sure we get an integer comparison.
  • We use the "spaceship operator" for comparison; which will return 0, 1, or -1 (see link), which is what sort expects the block to return.
  • We use uniq! to modify the Array in-place, use this by the first entry.
Community
  • 1
  • 1
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
  • What does (:&first) do? What if I want it to be the 208th value? should I write &:twohundredandeigth. I'm not criticising, I just don't understand. Please help. – user3505901 Aug 04 '16 at 21:03
  • @user3505901 `my_csv.uniq!(&:method_name)` is a shortcut for doing `my_csv.uniq! { |c| c.method_name }`. The `first` method is the same as using `[0]`, except that it looks a bit nicer in my opinion. You could also use `my_csv.uniq! { |c| c[0] }`, and if you want to get the 208th value, you could use `c[208]` :-) In standard Ruby, only `first` and `last` work, although Ruby on Rails defines a few more (`second`, `third`, etc.) – Martin Tournoij Aug 04 '16 at 21:14