简体   繁体   中英

Write into CSV from a hash in ruby

I'm trying to write into a CSV some Hash elements. @boo_hoo is my hash for each of its keys, if they have a single value, I don't want them in the CSV. There must be something wrong with my syntax. Could someone please explain a bit how to access the key+values of a hash in this case? Thanks!

CSV.open("final_data.csv", "wb") {|csv| 
    @boo_hoo.to_a.each.count {|k, v|
        count.v > 1 csv << |k, v|
    } 
}

Welcome to Stack Overflow. When you next write a post, you can use the code formatting tools to make it a bit easier to read.

I can see a few errors here.

  1. As per Mark's comment, count.v should be v.count .
  2. You've combined two statements on one line with no separator, so I'd guess your error message is like unexpected tIDENTIFIER, expecting end-of-input . You want to chain them together so that if your condition is met, then the args are added to the csv.
  3. Vertical pipes |k, v| are used to denote block arguments in ruby, but you're repeating them when you probably want an array.
  4. I don't really see what .to_a.each.count is doing for you, except possibly causing more syntax errors.

To write this in one line:

CSV.open("final_data.csv", "wb") {|csv| @boo_hoo.each {|k, v| csv << [k, v] if v.count > 1 } }

That might be a bit long, so I'd be tempted to break out the block into a multiline block:

CSV.open("final_data.csv", "wb") do |csv| 
  @boo_hoo.each {|k, v| csv << [k, v] if v.count > 1 } 
end

EDIT: You've edited your post as I wrote this. In ruby, it's an idiom to use single braces {} for a block consisting of a single line of code, but do ... end for a block that stretches over multiple lines.

Also, in response to Mudasobwa's comment, you probably want to add a splat operator [k,*v] . My code is valid ruby, but the output probably isn't what you want. Let's say @boo_hoo = {:a=>[1, 2, 3], :b=>[1], :c=>[1, 2]} . The code above produces the output

a,"[1, 2, 3]"
c,"[1, 2]"

If you change the block to

@boo_hoo.each {|k, v| csv << [k, *v] if v.count > 1 }

you get the output

a,1,2,3
c,1,2

which is almost certainly what you actually want in a CSV.

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