Write bunch of hashes to a json file - ruby-on-rails

Whats the right approach to write number of hashesh to a json file that can be parsed effeciently later on.
e.g:
hash1 = {:a=>1,:b=>'foo'}
hash2 = {:c=>3,:b=>'bar'}
...
hashN = {...}
File.open("data.json", "a") { |io| io.write(hash1.to_json)}
I can write a comma after each hash to the file, but this is not looking nice to me.. is it a better way to do it?

that can be parsed effeciently later on.
You will want to put your hashes in a list so that later you can load and parse everything in one sweep:
require 'json'
arr = []
arr << {:a=>1,:b=>'foo'}
arr << {:c=>3,:b=>'bar'}
json_str = arr.to_json
File.open("yourfile", 'w') { |file| file.write(json_str) }
Later on to load:
contents = File.read('yourfile')
arr = JSON.parse(contents)

Related

Extract Substring from String / Ruby

I get the datas from a variable called "apps".
And I have this datastructure:
{"id"=>001,
"name"=>"test01",
"users"=>
[{"id"=>01,
"name"=>"test02"},
{"id"=>02,
"name"=>"test03"}]}
How can I extract the namevalues from the users substring?
I have tried
apps.each do |test|
data = Hash.new
data['id'] = test['id']
data['name'] = test['name']
data['username'] = test['users.name']
userdata = data
userdata.each do |row|
File.write('test.yaml', row.to_yaml)
end
end
But that doesn't work.
desired output would be:
{"id"=>"01", "name"=>"test02","id"=>"02", "name"=>"test03"}
you just need to require 'yaml' in order to use it on Hash/Array classes, you don't need to iterate over array or hash, to_yaml already handles this for you.
require 'yaml'
data = {"id"=>001,
"name"=>"test01",
"users"=>
[{"id"=>01,
"name"=>"test02"},
{"id"=>02,
"name"=>"test03"}]}
File.write('test.yml', data["users"].to_yaml)

Not able to place csv data in a Hash

I have a CSV file with two columns:
PPS_Id Amount
123 100
1234 150
I read data from this file and insert in a array using the code below:
CSV.foreach("filename.CSV", headers: true) do |row|
file_details << row.inspect # hash
end
I am then trying to push the data in the file_details into a hash with PPS_Id as key and Amount as Value, I am using the code below:
file_details_hash = Hash.new
file_details.each { |x|
file_details_hash[x['PPS_Id']] = x['Amount']
}
But when I print the result I get nothing just {"PPS_Id"=>"Amount"}
Can you please help
Your code, modified to work
You need to specify the column separator for your csv, and remove inspect.
require 'csv'
file_details = []
CSV.foreach("filename.CSV", headers: true, col_sep: "\s" ) do |row|
file_details << row
end
file_details_hash = Hash.new
file_details.each { |x|
file_details_hash[x['PPS_Id']] = x['Amount']
}
p file_details_hash
#=> {"123"=>"100", "1234"=>"150"}
It now returns what you expected to get.
Shorter solution
Read the csv, drop the first line (header) and convert to a Hash :
p CSV.read("filename.CSV", col_sep: "\s").drop(1).to_h
#=> {"123"=>"100", "1234"=>"150"}
First of all, you are collecting strings into an array (see String#inspect):
file_details << row.inspect
After that you call (sic!) String#[] on that strings:
x['PPS_Id'] #⇒ "PPS_Id", because string contains this substring
That said, your code has nothing but errors. You might achieve what you want with:
csv = CSV.parse(File.read("filename.CSV"), col_sep: "\s")
csv[1..-1].to_h
#⇒ {
# "123" => "100",
# "1234" => "150"
# }
Using inspect will save your CSV rows as strings, so obviously you won't be able get what you need. Instead try this:
file_details = CSV.read("filename.csv")
Read CSV directly will create an 2D array that you can then iterate over, which will look like this: [["PPS_Id", "Amount"], ["123", "100"], ["1234", "150"]]
From there you can slightly modify your approach:
file_details.each do |key, value|
file_details_hash[key] = value
end
To receive a hash like this: {"PPS_Id"=>"Amount", "123"=>"100", "1234"=>"150"}

creating an array using find method in rails

input = {"color"=>["red"],"size"=>["s","l"]}
json_obj = [{"color":"red","id":"123","size":"s","name":"test"},
{"color":"yellow","id":"124","size":"s","name":"test"},
{"color":"red","id":"125","size":"l","name":"test"}]
Output should be
output["red_s"] = {"color":"red","id":"123","size":"s","name":"test"}
output["red_l"] = {"color":"red","id":"125","size":"l","name":"test"}
output is the combinations of the input and a find on the json_obj.
How to get the output in rails?
I have the below script to get the combinations ie.red_s and red_l,
ary = input.map {|k,v| [k].product v}
output = ary.shift.product(*ary).map {|a| Hash[a]}
And
output[red_s]=json_obj.find{|h| h["color"] == "red" and h["size"] == "S"}
I don't want to have any hardcodings in code like color and size as above.
I think this should get you close to what you want.
Note the "ticks" around your json array object (what you had is not valid ruby)
The other issue is you would have to figure a better way to create the output hash key.
require 'json'
input = {"color"=>["red"],"size"=>["s","l"]}
output = {}
json_obj = '[{"color":"red","id":"123","size":"s","name":"test"},
{"color":"yellow","id":"124","size":"s","name":"test"},
{"color":"red","id":"125","size":"l","name":"test"}]'
found = JSON.parse json_obj
input.each_key do |key|
found = found.select { |item| input[key].include?(item[key]) }
end
puts found
found.each do |item|
output_key = ""
input.each_key do |key|
output_key = "#{item[key]}_" + output_key
end
output["#{output_key}"] = item.to_json
end
puts output

How do I strip a URL from a string and place it an array?

I'm working on building a small script that searches for the 5 most recent pictures tweeted by a service, isolates the URL and puts that URL into an array.
def grabTweets(linkArray) #brings in empty array
tweets = Twitter.search("[pic] "+" url.com/r/", :rpp => 2, :result_type => "recent").map do |status|
tweets = "#{status.text}" #class = string
url_regexp = /http:\/\/\w/ #isolates link
url = tweets.split.grep(url_regexp).to_s #chops off link, turns link to string from an array
#add link to url array
#print linkArray #prints []
linkArray.push(url)
print linkArray
end
end
x = []
timelineTweets = grabTweets(x)
The function is returning things like this: ["[\"http://t.co/6789\"]"]["[\"http://t.co/12345\"]"]
I'm trying to get it to return ["http://t.co/6789", "http://t.co/1245"] but it's not managing that.
Any help here would be appreciated. I'm not sure what I'm doing wrong.
The easiest way to grab URLs in Ruby is to use the URI::extract method. It's a pre-existing wheel that works:
require 'uri'
require 'open-uri'
body = open('http://www.example.com').read
urls = URI::extract(body)
puts urls
Which returns:
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
http://www.w3.org/1999/xhtml
http://www.icann.org/
mailto:iana#iana.org?subject=General%20website%20feedback
Once you have the array you can filter for what you want, or you can give it a list of schemes to extract.
To strip a url out a string and push into urls array, you can do:
urls = []
if mystring =~ /(http:\/\/[^\s]+)/
urls << $1
end
grep returns an array:
grep(pattern) → array
grep(pattern) {| obj | block } → array
Returns an array of every element in enum for which Pattern === element.
So your odd output is coming from the to_s call the follows your grep. You're probably looking for this:
linkArray += tweets.split.grep(url_regexp)
or if you only want the first URL:
url = tweets.split.grep(url_regexp).first
linkArray << url if(url)
You could also skip the split.grep and use scan:
# \S+ should be good enough for this sort of thing.
linkArray += tweets.scan(%r{https?://\S+})
# or
url = tweets.scan(%r{https?://\S+}).first
linkArray << url if(url)

Split a string into an array of numbers

My string:
>> pp params[:value]
"07016,07023,07027,07033,07036,07060,07062,07063,07065,07066,07076,07081,07083,07088,07090,07092,07201,07202,07203,07204,07205,07206,07208,07901,07922,07974,08812,07061,07091,07207,07902"
How can this become an array of separate numbers like :
["07016", "07023", "07033" ... ]
result = params[:value].split(/,/)
String#split is what you need
Try this:
arr = "07016,07023,07027".split(",")
Note that what you ask for is not an array of separate numbers, but an array of strings that look like numbers. As noted by others, you can get that with:
arr = params[:value].split(',')
# Alternatively, assuming integers only
arr = params[:value].scan(/\d+/)
If you actually wanted an array of numbers (Integers), you could do it like so:
arr = params[:value].split(',').map{ |s| s.to_i }
# Or, for Ruby 1.8.7+
arr = params[:value].split(',').map(&:to_i)
# Silly alternative
arr = []; params[:value].scan(/\d+/){ |s| arr << s.to_i }

Resources