Create JSON from two arrays - arrays

I have two arrays say: x=[1,2,3] and y=['a', 'b', 'c']. I want to create a json using x and y arrays in rails console. What is the optimized way to do it.
The desired JSON should looks like this:
{
"obj":
[
{
"key":"a",
"value": 1
},
{
"key":"b",
"value": 2
},
{
"key":"c",
"value": 3
}
]
}

x = [1,2,3] and y = ['a', 'b', 'c']
{obj: y.zip(x).map { |k, v| {key: k, value: v} } }
#⇒ {
# :obj => [
# {
# :key => "a",
# :value => 1
# },
# {
# :key => "b",
# :value => 2
# },
# {
# :key => "c",
# :value => 3
# }
# ]
# }
If you insist on having string keys:
{ 'obj' => y.zip(x).map { |k, v| { 'key' => k, 'value' => v } } }
To get a json out of the hash, just call to_json on it.

Related

entering values into an array in react from given 2d array

I want to enter the first value from every array inside a 2d array, I get the 2d array from the server and my intentions are to use it in one of the client pages (as chart data).
Here is the relevant code:
React.useEffect(() => {
fetch("http://localhost:3001/bitcoin")
.then((res) => res.json())
.then((data) => setData(data.message))
.then((dates) => {
//code right here
})
}, []);
Any idea how to implement it?
first method :
you can use for...of like this :
const Arr = [
[ 1,2,3,4],
['one', 'two' , 'three'],
['un' ,'deux', 'trois' ],
]
const ArrOfFirstValues = []
for(key of Arr){
ArrOfFirstValues.push(key[0])
}
console.log(ArrOfFirstValues)
the output is : [ 1, 'one', 'un' ]
Second method :
you can use .map to iterate it :
const Arr = [
[ 1,2,3,4],
['one', 'two' , 'three'],
['un' ,'deux', 'trois' ],
]
console.log(Arr )
const ArrOfFirstValues = Arr.map(arr => arr[0])
console.log(ArrOfFirstValues)
the output will be :
[ 1, 'one', 'un' ]
It's too easy :
const twoDArray = [
["a", "b", "c"],
["A", "B", "C"],
["aa", "bb", "cc"],
["AA", "BB", "CC"] ]
const firstElements = twoDArray.map(item => item[0]);
console.log(firstElements);
// answer: [ 'a', 'A', 'aa', 'AA' ]
Let me know if it is what you exactly need.
Update :
That was the main idea you need and you can implement like this:
React.useEffect(() => {
fetch("http://localhost:3001/bitcoin")
.then(res => res.json())
.then(jsonData => {
// I assume that jsonData is your 2D array
const twoDimensionArr = jsonData ;
setData(twoDimensionArr);
const firstElementsArr = twoDimensionArr.map(item => item[0]);
console.log(firstElementsArr);
})
}, []);

How to check if hash keys match value from array

I have:
arr = ['test', 'testing', 'test123']
ht = {"test": "abc", "water": "wet", "testing": "fun"}
How can I select the values in ht whose key matches arr?
ht_new = ht.select {|hashes| arr.include? hashes}
ht_new # => "{"test": "abc", "testing": "fun"}"
Additionally, how can we return values from:
arr = ["abc", "123"]
ht = [{"key": "abc", "value": "test"}, {"key": "123", "value": "money"}, {"key": "doremi", "value": "rain"}}]
output # => [{"key": "abc", "value": "test"}, {"key": "123", "value": "money"}]
Only a slight change is needed:
ht.select { |k,_| arr.include? k.to_s }
##=> {:test=>"abc", :testing=>"fun"}
See Hash#select.
The block variable _ (a valid local variable), which is the value of key k, signifies to the reader that it is not used in the block calculation. Some prefer writing that |k,_v|, or some-such.
One option is mapping (Enumerable#map) the keys in arr:
arr.map.with_object({}) { |k, h| h[k] = ht[k.to_sym] }
#=> {"test"=>"abc", "testing"=>"fun", "test123"=>nil}
If you want to get rid of pairs with nil value:
arr.map.with_object({}) { |k, h| h[k] = ht[k.to_sym] if ht[k.to_sym] }
#=> {"test"=>"abc", "testing"=>"fun"}
This is an option for the last request:
ht.select{ |h| h if h.values.any? { |v| arr.include? v} }
# or
arr.map { |e| ht.find { |h| h.values.any?{ |v| v == e } } }
#=> [{:key=>"abc", :value=>"test"}, {:key=>"123", :value=>"money"}]
A straightforward way is:
ht.slice(*arr.map(&:to_sym))
# => {:test => "abc", :testing => "fun"}

Changing a hash to an array of hash

I want to transform this ruby hash structure into an array of hash. The end structure will be used in the charts api, Thanks in advance
From:
data =
{
["Transportations", "Not-Approved"] => 350,
["Transportations", "Approved"] => 160,
["Communications", "Not-Approved"] => 300,
["Communications","Approved"] => 80,
["Rentals","Not-Approved"] => 50,
["Rentals", "Approved"] => 145,
["Salaries","Not-Approved"] => 150,
["Salaries", "Approved"] => 310
}
To:
data = [
{
name: "Transportations",
data: [["Not-Approved", 350], ["Approved", 160]]
},
{
name: "Communications",
data: [["Not-Approved", 300], ["Approved", 80]]
},
{
name: "Rentals",
data: [["Not-Approved", 50], ["Approved", 145]]
},
{
name: "Salaries",
data: [["Not-Approved", 150], ["Approved", 310]]
}
]
Code
def rearrange(data)
data.group_by { |k,_| k.first }.map { |name, arr|
{ name: name, data: arr.map { |(_,outcome), val| [outcome, val] } } }
end
Example
data = {
["Transportations", "Not-Approved"] => 350,
["Transportations", "Approved"] => 160,
["Communications", "Not-Approved"] => 300,
["Communications","Approved"] => 80,
["Rentals","Not-Approved"] => 50,
["Rentals", "Approved"] => 145,
["Salaries","Not-Approved"] => 150,
["Salaries", "Approved"] => 310
}
rearrange(data)
#=> [{:name=>"Transportations",
# :data=>[["Not-Approved", 350], ["Approved", 160]]},
# {:name=>"Communications",
# :data=>[["Not-Approved", 300], ["Approved", 80]]},
# {:name=>"Rentals",
# :data=>[["Not-Approved", 50], ["Approved", 145]]},
# {:name=>"Salaries",
# :data=>[["Not-Approved", 150], ["Approved", 310]]}
# ]
Explanation
The first step is as follows.
h = data.group_by { |k,_| k.first }
#=> { "Transportations"=>[
# [["Transportations", "Not-Approved"], 350],
# [["Transportations", "Approved"], 160]
# ],
# "Communications"=>[
# [["Communications", "Not-Approved"], 300],
# [["Communications", "Approved"], 80]
# ],
# "Rentals"=>[
# [["Rentals", "Not-Approved"], 50],
# [["Rentals", "Approved"], 145]
# ],
# "Salaries"=>[
# [["Salaries", "Not-Approved"], 150],
# [["Salaries", "Approved"], 310]
# ]
# }
Enumerable#group_by's second block variable holds the value of the key (the key being the first block variable). For example, when the key is ["Transportations", "Not-Approved"] the value is 350. I have assigned the block variable _ (a valid local variable) to the value, mainly to inform the reader that it is not used in the block calculation.
To understand the second step, the mapping of the key-value pair of h, first define
enum = h.map
#=> #<Enumerator:
# {"Transportations"=>[
# [["Transportations", "Not-Approved"], 350],
# [["Transportations", "Approved"], 160]
# ], "Communications"=>[
# ...
# [["Salaries", "Approved"], 310]]}:map>
The first element of enum is generated and passed to the block, and the block variables are assigned values using parallel assignment.
name, arr = enum.next
#=> ["Transportations", [
# [["Transportations", "Not-Approved"], 350],
# [["Transportations", "Approved"], 160]
# ]
# ]
name
#=> "Transportations"
arr
#=> [
# [["Transportations", "Not-Approved"], 350],
# [["Transportations", "Approved"], 160]
# ]
map's block calculation is then performed. First, calculate
a = arr.map { |(_,outcome), val| [outcome, val] }
#=> [["Not-Approved", 350], ["Approved", 160]]
Then construct the hash for `"Transportation".
{ name: name, data: a }
#=> {:name=>"Transportations",
# :data=>[["Not-Approved", 350], ["Approved", 160]]}
The remaining calculations are similar.
Try this,
h = Hash.new { |h, k| h[k] = { name: k, data: {} }}
data.each { |(name, each), value| h[name][:data][each] = value };
h.values.each { |each| each[:data] = each[:data].to_a }
array = h.values

hash with array as a key, how to fetch by fist value in the hash

I have a grouped hash created with a group_by which creates an Array as a key:
#lines.group_by{|e| [e.activity, e.subactivity]}
Therefore, my resultant hash looks like this one:
{[7, 6]=>
[{:field_one=>"AAA",
:field_two=>"BBB",
:activity=>7,
:subactivity=>6}],
[1,0] =>
[{:field_one=>"CCC",
:field_two=>"DDD",
:activity=>1,
:subactivity=>0}],
[1,7] =>
[{:field_one=>"EEE",
:field_two=>"FFF",
:activity=>1,
:subactivity=>7}],
}
I would like to get an array with all the values for keys such as [1, *]. So, the result would be:
[{:field_one=>"CCC",
:field_two=>"DDD",
:activity=>1,
:subactivity=>0},
{:field_one=>"EEE",
:field_two=>"FFF",
:activity=>1,
:subactivity=>7}]
How can I do this?
h.select { |(f,_),v| f==1 }.values
or
h.values_at(*h.keys.select { |f,_| f==1 })
If the keys were arrays of one or more elements, possibly varying in size, but you were only concerned with the first element (as here), you would write:
h.select { |(f,*_),v| f==1 }.values
or just
h.select { |(f,*),v| f==1 }.values
Maybe this will helps.
Input
h = {
[7, 6] =>
[
{:field_one => "AAA",
:field_two => "BBB",
:activity => 7,
:subactivity => 6}
],
[1, 0] =>
[
{:field_one => "CCC",
:field_two => "DDD",
:activity => 1,
:subactivity => 0}
],
[1, 7] =>
[
{:field_one => "EEE",
:field_two => "FFF",
:activity => 1,
:subactivity => 7}
],
}
code:
h.keys.group_by { |a| a[0] }.each_with_object({}) do |(k, keys), exp|
exp[k] = keys.map { |key| h[key] }.flatten
end
output
{
7 => [
{:field_one => "AAA", :field_two => "BBB", :activity => 7, :subactivity => 6}
],
1 => [
{:field_one => "CCC", :field_two => "DDD", :activity => 1, :subactivity => 0},
{:field_one => "EEE", :field_two => "FFF", :activity => 1, :subactivity => 7}
]
}
If any key can include the number 1 then use #include?:
vals.select { |k, _v| k.include?(1) }.values.flatten
=> [{:field_one=>"CCC", :field_two=>"DDD", :activity=>1, :subactivity=>0}, {:field_one=>"EEE", :field_two=>"FFF", :activity=>1, :subactivity=>7}]
Or if the first value in the key must be a 1 then:
vals.select { |k, _v| k[0] == 1 }.values.flatten
=> [{:field_one=>"CCC", :field_two=>"DDD", :activity=>1, :subactivity=>0}, {:field_one=>"EEE", :field_two=>"FFF", :activity=>1, :subactivity=>7}]
suppose h is your hash, then:
arr = []
h.each do |k,v|
arr << v if k.first == 1
end

A hash inside an array [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have this hash:
{"id" => [323, 324], info => ["Test Info", "Test Info2"]}
I would like to have a hash inside an array like this:
array = [
[{"id" => "323", info => "Test Info"}],
[{"id" => "324", info => "Test Info2"}]
]
I have duplicate data. I need to use uniq on id and info to get each id only once. Because of that, I need to join them afterwards.
h = {"id" => [323, 324], "info" => ["Test Info", "Test Info2"]}
h.map { |k, v| [k].product v }.transpose.map &:to_h
#⇒ [
# [0] {
# "id" => 323,
# "info" => "Test Info"
# },
# [1] {
# "id" => 324,
# "info" => "Test Info2"
# }
]
If you want to wrap each nested hash into it’s own array, one more action is required:
h.map { |k, v| [k].product v }.transpose.map(&:to_h).map { |e| [e] }
#⇒ [
# [0] [
# [0] {
# "id" => 323,
# "info" => "Test Info"
# }
# ],
# [1] [
# [0] {
# "id" => 324,
# "info" => "Test Info2"
# }
# ]
# ]
You can use this solution (maybe so OP in this case)
h = {"id" => [323, 324], "info" => ["Test Info", "Test Info2"]}
h.values.transpose.map do |a|
[Hash[h.keys.each_with_index.map { |k, i| [k, a[i]] }]]
end
# => [[{"id"=>323, "info"=>"Test Info"}], [{"id"=>324, "info"=>"Test Info2"}]]
This looks like a job for zip which zippers together two arrays:
hash = {
"id" => [323, 324],
"info" => ["Test Info", "Test Info2"]
}
keys = %w[ id info ]
array = hash['id'].zip(hash['info']).map do |id, info|
Hash[keys.zip(pair)]
end
# => [{"id"=>323, "info"=>"Test Info"}, {"id"=>324, "info"=>"Test Info2"}]
The Hash[] method is used to convert an array of form [['a',1],['b',2]] to a hash of form {'a'=>1,'b'=>2}.
Here are a couple more:
h = {"id" => [323, 324], "info" => ["Test Info", "Test Info2"]}
da_keys = h.keys
h.values.transpose.each_with_object([]) { |a,b| b << da_keys.zip(a).to_h }
#=> [{"id"=>323, "info"=>"Test Info"}, {"id"=>324, "info"=>"Test Info2"}]
rolling_keys = h.keys.cycle
h.values.transpose.map {|a| a.each_with_object({}) {|v,g| g.update(rolling_keys.next=>v)}}
#=> [{"id"=>323, "info"=>"Test Info"}, {"id"=>324, "info"=>"Test Info2"}]
You asked for this:
array = [
[{"id" => "323", info => "Test Info"}],
[{"id" => "324", info => "Test Info2"}]
]
But I assume what you really want is just this:
array = [
{"id" => "323", "info" => "Test Info"},
{"id" => "324", "info" => "Test Info2"}
]
Given this:
h = {"id" => [323, 324], "info" => ["Test Info", "Test Info2"]}
You can do this:
h.map { |k,l| l.map { |v| [ k,v ] } }.reduce(&:zip).map(&:to_h)

Resources