How to define the two-dimensional array in JSON schema? The problem is that I know, how to define a 2D array with exact items count in a row:
{
type: "array",
items: {
type: "array",
items: {
type: "number",
minItems: 2,
maxItems: 2
}
},
}
But I cannot understand, how to define an array that has exactly the same number of items in each row when this number is not fixed. In other words, I need to define a rectangular shape of a 2D array.
This data should be valid:
[
[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
]
and this data also should be valid:
[
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
]
This shouldn't:
[
[1, 2, 3],
[1, 2],
[1, 2, 3],
]
and this shouldn't:
[
[1, 2, 3, 4],
[1, 2, 3],
[1, 2, 3],
]
I don't believe this is possible with JSON Schema because you can't provide dynamic values relating to the instance JSON to the JSON Schema.
Related
I have this JSON data coming from the server and I want to make a bar chart in react with it but because there is only one date for each index of arrays is there any charting library that supports this or any other solutions?
results: [{
date: '1399/1/1',
remove: {
done: [6, 6, 1, 6],
declined: [2, 7, 1, 6]
},
add: {
done: [5, 6, 1, 6],
declined: [2, 7, 1, 6]
}
}, {
date: '1399/2/1',
remove: {
done: [2, 7, 1, 6, 8, 1],
declined: [2, 7, 1, 6]
},
add: {
done: [5, 9, 1, 6],
declined: [2, 7, 1, 6, 6]
}
}
]
also, I want to give each bar a custom color based on whether it is done or declined.
I have an array that looks like this:
original = [[1, 2, 3], [2, 2, 2], [1, 2, 3], [2, 2, 2], [2, 2, 3], [1, 2, 2], [5, 4, 2]]
I'd like to get a new array whose elements that match the second and third position would sum up its first position to get this:
expected_output = [[4, 2, 3], [5, 2, 2], [5, 4, 2]]
I got to grouping the elements from the array as follows:
new_array = original.group_by {|n| n[1] && n[2] }
# => {3=>[[1, 2, 3], [1, 2, 3], [2, 2, 3]], 2=>[[2, 2, 2], [2, 2, 2], [1, 2, 2], [5, 4, 2]]}
It is still far from my desired output.
Here's one way to return a new array of arrays where the first element of each array is the sum of the original array's first element where its second and third elements match:
arr = [[1, 2, 3], [2, 2, 2], [1, 2, 3], [2, 2, 2], [2, 2, 3], [1, 2, 2], [5, 4, 2]]
array_groups = arr.group_by { |sub_arr| sub_arr[1, 2] }
result = array_groups.map do |k, v|
k.unshift(v.map(&:first).inject(:+))
end
result
# => [[4, 2, 3], [5, 2, 2], [5, 4, 2]]
Hope this helps!
This will produce a similar result using an array grouping rather than combining the two latter numbers.
original = [[1, 2, 3], [2, 2, 2], [1, 2, 3], [2, 2, 2], [2, 2, 3], [1, 2, 2], [5, 4, 2]]
new = original.group_by {|n| [n[1], n[2]] }
added = new.map{|x| [new[x.first].map(&:first).inject(0, :+),x.first].flatten}
puts added.to_s
original.each_with_object(Hash.new(0)) { |(f,*rest),h| h[rest] += f }.
map { |(s,t),f| [f,s,t] }
# => [[4, 2, 3], [5, 2, 2], [5, 4, 2]]
Note that
original.each_with_object(Hash.new(0)) { |(f,*rest),h| h[rest] += f }
#=> {[2, 3]=>4, [2, 2]=>5, [4, 2]=>5}
Hash.new(0) is sometimes called a counting hash. To understand how that works, see Hash::new, especially the explanation of the effect of providing a default value as an argument of new. In brief, if a hash is defined h = Hash.new(0), then if h does not have a key k, h[k] returns the default value, here 0 (and the hash is not changed).
I have an array:
[1, 4, 4, 4, 2, 9, 0, 4, 3, 3, 3, 3, 4]
and want to replace the repeating values with a string "repeat". The repeated 4 at indices 1, 2, 3 and 3 at indices 8, 9, 10, 11 should be replaced. I should get:
[1, "repeat", 2, 9, 0, 4, "repeat", 4]
How is this accomplished?
Here are two ways you could do that.
#1 Use Enumerable#chunk:
arr = [1,4,4,4,2,9,0,4,3,3,3,3,4]
arr.chunk(&:itself).map { |f,a| a.size==1 ? f : "repeat" }
#=> [1, "repeat", 2, 9, 0, 4, "repeat", 4]
The steps:
enum = arr.chunk(&:itself)
#=> #<Enumerator: #<Enumerator::Generator:0x007febc99fb160>:each>
We can view the elements of this enumerator by converting it to an array:
enum.to_a
#=> [[1, [1]], [4, [4, 4, 4]], [2, [2]], [9, [9]], [0, [0]],
# [4, [4]], [3, [3, 3, 3, 3]], [4, [4]]]
Object#itself was added in Ruby v2.2. For earlier version you would use
enum = arr.chunk { |e| e }
It is now a simple matter to map the elements of enum as required:
enum.map { |f,a| a.size==1 ? f : "repeat" }
#=> [1, "repeat", 2, 9, 0, 4, "repeat", 4]
#2 Use Enumerable#slice_when
arr.slice_when { |e,f| e !=f }.map { |a| a.size==1 ? a.first : "repeat" }
The steps:
enum = arr.slice_when { |e,f| e !=f }
#=> #<Enumerator: #<Enumerator::Generator:0x007febc99b8cc0>:each>
a = enum.to_a
#=> [[1], [4, 4, 4], [2], [9], [0], [4], [3, 3, 3, 3], [4]]
a.map { |a| a.size==1 ? a.first : "repeat" }
#=> [1, "repeat", 2, 9, 0, 4, "repeat", 4]
slice_when was introduced in Ruby v.2.2.
I use nvd3-line-chart angularjs directive.
My data is:
$scope.exampleData = [
{
"key": "Series 1",
"values": [ [1, 2], [2, 10], [3, 6], [4, 15], [5, 8] ]
},
{
"key": "Series 2",
"values": [ [1, 5], [2, 30], [3, 8], [4, 11], [5, 4] ]
},
{
"key": "Series 3",
"values": [ [1, 2000], [2, 10000], [3, 600], [4, 1500], [5, 8000] ]
}
]
Html:
nvd3-line-chart(
data="exampleData"
id="graph-Data-1"
width="1170"
height="494"
showXAxis="true"
showYAxis="true"
tooltips="true"
useInteractiveGuideline="true"
showLegend="true"
ng-if="exampleData"
)
How i can assign Y2 to Series 3 data? I found line-plus-bar-chart directive but how can i implement this via nvd3-line-chart directive?
I'm afraid you can't use your data to render a secondary axis. It is out of the scope of the data itself.
The best thing you could do is to trick it yourself: http://www.d3noob.org/2013/01/using-multiple-axes-for-d3js-graph.html
I have array:
a = [1, 3, 1, 3, 2, 1, 2]
And I want to group by values, but save it indexes, so result must be looks like this:
[[0, 2, 5], [1, 3], [4, 6]]
or hash
{1=>[0, 2, 5], 3=>[1, 3], 2=>[4, 6]}
Now I'm using pretty ugly and big code:
struc = Struct.new(:index, :value)
array = array.map.with_index{ |v, i| struc.new(i, v) }.group_by {|s| s[1]}.map { |h| h[1].map { |e| e[0]}}
`
If you use a hash with a default value to avoid iterating twice over the elements:
a = [1, 3, 1, 3, 2, 1, 2]
Hash.new { |h, k| h[k] = [] }.tap do |result|
a.each_with_index { |i, n| result[i] << n }
end
#=> { 1 => [0, 2, 5], 3 => [1, 3], 2 => [4, 6] }
a = [1, 3, 1, 3, 2, 1, 2]
a.each_with_index.group_by(&:first).values.map { |h| h.map &:last }
First we get an Enumerator in the form [val, idx], ... (each_with_index), then group_by the value (first value in pair), then take the index (last element) of each pair.
You can use:
Enumerable#each_with_index
Enumerable#group_by and
Array#transpose:
a = [1, 3, 1, 3, 2, 1, 2]
a.each_with_index.group_by(&:first).values.map { |b| b.transpose.last }
#=> [[0, 2, 5], [1, 3], [4, 6]]