I have two simple ruby arrays and a JSON string mapping the elements of the first array to the elements of the second array:
keys = [:key0, :key1, :key2]
values = [:value0, :value1, :value2]
jsonString = {keys[0] => values[0], keys[1] => values[1], keys[2] => values[2]}
Writing this to a file:
file.write(JSON.pretty_generate(jsonString))
results into a nicely printed json object:
{
"key0": "value0",
"key1": "value1",
"key2": "value2"
}
But how can I generate the same output of two much bigger arrays without listing all these elements explicitly?
I just need something like
jsonString = {keys => values}
but this produces a different output:
{
"[:key0, :key1, :key2]":
[
"value0",
"value1",
"value2"
]
}
How can I map the two without looping over both?
array = keys.zip(values)
#=> [[:key0, :value0], [:key1, :value1], [:key2, :value2]]
Array#zip merges elements of self to the corresponding elements of the argument array and you get an array of arrays. This you can convert into a hash ...
hash = array.to_h
# => {:key0=>:value0, :key1=>:value1, :key2=>:value2}
... and the hash you can turn into a json string.
jsonString = JSON.pretty_generate(hash)
puts jsonString
#{
# "key0": "value0",
# "key1": "value1",
# "key2": "value2"
#}
Use Array#zip to make pairs of values and then make hash of them:
keys = [:key0, :key1, :key2]
values = [:value0, :value1, :value2]
Hash[keys.zip values]
# => {:key0=>:value0, :key1=>:value1, :key2=>:value2}
Related
I'm writing a fact for Puppet in Ruby. I have an array
array = [[["User", "Username"], ["Date", "16.12.2014"]], [["User1", "Username1"], ["Date1", "17.12.2014"]]]
I want to convert it to json. I tried to convert it to hash first, but doing like this in Linux
array.each do |userarr|
winusers = Hash[userarr.map! { |pair| [pair[0], pair[1]] } ]
end
I get only the this one [["User1", "Username1"], ["Date1", "17.12.2014"]] pair converted. Doing like this:
array.each do |userarr|
winusers = Hash[userarr.map! { |pair| [pair[0], pair[1]] } ]
winusersa << winusers
end
I get an array of hashes. Coverting it to json winusersa.to_json on Linux I get an array of json format text, on Puppet (facter in fact) I get only the first pair converted. Why in Puppet fact it doesn't work? How to convert that array to get all pairs well formated?
Try this one
array.flatten(1).each_slice(2).map(&:to_h)
=> [{"User"=>"Username", "Date"=>"16.12.2014"}, {"User1"=>"Username1", "Date1"=>"17.12.2014"}]
And then, as an hash, you can easily call to_json
You've already got your Array in the form that the ruby Hash#[] method can consume. I think all you need is this:
% pry
[1] pry(main)> require 'json'
[2] pry(main)> a = [[["User", "Username"], ["Date", "16.12.2014"]], [["User1", "Username1"], ["Date1", "17.12.2014"]]]
[3] pry(main)> puts JSON.pretty_generate(a.map { |e| Hash[e] })
[
{
"User": "Username",
"Date": "16.12.2014"
},
{
"User1": "Username1",
"Date1": "17.12.2014"
}
]
Require 'facter' #if you have facter as gem to test locally require 'json'
array = [
[
["User", "Username"],
["Date", "16.12.2014"]
],
[
["User1", "Username1"],
["Date1", "17.12.2014"]
]
]
put JSON.pretty_generate(JSON.parse(array.to_json))
i have the following Array Object :
[
{
"key1": abc,
"key2":xyz
},
{
"key1": abc,
"key2":xyz
}
]
Now what i want is to print "key1" & "key2". I know we can iterate through values using map, but i also want to iterate through Array keys.
Assuming ArrayObj contains the key:value pairs, we can do the following:
let keys = Object.keys(ArrayObj);
for(index=0;index<keys.length;index++)
{
console.log(keys[index]);
}
I have an array of hashes that I would like to sort based on the :reference values. But some of the elements within the array do not have a :reference key and therefore cannot be sorted. Is there a way to ignore this field and just sort the hash elements that contain this key?
I've tried the following approach but I'm getting an argument error
ArgumentError: comparison of NilClass with String failed
sort_by at org/jruby/RubyEnumerable.java:503
arr1 = [{:reference=> "F123",
:name=> "test4"
},
{
:reference=> "ZA4",
:name=> "test3"
},
{
:reference=> "A43",
:name=> "test2"
},
{
:name=> "test1"
},
{
:name=> "homework1"
}]
arr1 = arr1.sort_by { |hash| hash[:reference] }
puts arr1
The correct output should look like this :
=> arr1= [
{:reference=>"A43", :name=>"test2"},
{:reference=>"F123", :name=>"test4"},
{:reference=>"ZA4", :name=>"test3"},
{:name=> "test1"},
{:name=> "homework1"}
]
You can only sort on values that can be compared, so if you've got values of different types it's best to convert them to the same type first. A simple work-around is to convert to string:
arr1.sort_by { |hash| hash[:reference].to_s }
You can also assign a default:
arr1.sort_by { |hash| hash[:reference] || '' }
Edit: If you want the nil values sorted last:
arr1.sort_by { |hash| [ hash[:reference] ? 0 : 1, hash[:reference].to_s ] }
If you don't mind temporary variables, you could split the array into two arrays, one containing hashes with :reference and the other those without:
with_ref, without_ref = arr1.partition { |h| h[:reference] }
Then sort the first one:
with_ref.sort_by! { |h| h[:reference] }
And finally concatenate both arrays:
arr1 = with_ref + without_ref
The JSON-String:
jsonString = {"string1" => {"test1" => "test2"}}
results (with JSON.pretty_generate) in a pretty printed:
{
"string1":
{
"test1": "test2"
}
}
But when I try to add all elements of two arrays into this JSON-String
keys = [:key0, :key1]
values = [:value0, :value1]
my_hash = Hash[keys.zip values]
jsonString = {"string1" => {"test1" => "test2", my_hash}}
I'm always getting a:
syntax error, unexpected '}', expecting =>
jsonString = {"string1" => {"test1" => "test2", my_hash}}
I would have expected a behavior like this:
jsonString = {"string1" => {"test1" => "test2", keys[0] => values[0], keys[1] => values[1]}}
Output:
{
"string1":
{
"test1": "test2",
"key0": "value0",
"key1": "value1"
}
}
Is there a way to this using the hash-mechanism?
Thanks a lot.
Try jsonString.merge(my_hash) ?
My understanding is that the variable called jsonString is actually a hash, not a json string. If you wanted to convert that hash to a real JSON string, you could import the json module (using require 'json') than call jsonStrong.to_json, but once you've converted the hash to a string it's more difficult to had other hashes to it. It's best to add all the hashes together, then convert the result to json.
I have an array of arrays that I'd like to convert into json and output within another array. I have the following array:
weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]]
I would like to include this array within a JSON output like so:
json_output = { :results => weekdays.count, :data => weekdays }
Right now I get this, which just doesn't look right as there are not curly brackets around the "data" field...
{
"results": 2,
"data": [
["Monday", 2],
["Tuesday", 4],
["Thursday", 5]
]
}
Any help would be great!
The output is correct. Curly brackets are around hashes, but your data attribute is a nested array.
If you want to convert a nested array into a hash, just call to_h on it:
{ :results => weekdays.count, :data => weekdays.to_h }
Better to convert it to hash manually.
weekdays = [["Monday",2],["Tuesday",4],["Thursday",5]]
hash_weekdays = Hash.new
weekdays.each do |item|
hash_weekdays[item[0]] = item[1]
end
hash_weekdays #=> {"Monday"=>2, "Tuesday"=>4, "Thursday"=>5}