how to map json data into object - javascript

Question - How can mapp json data into objects? json can be found here
Details - I was able to connect to api and get the json data. Now i want to map 2 array data.hourly.time[] & data.hourly.temperature_2m[] into 1 DataTable? I need datatable inorder to display json data into google charts api Below is a example of datable format that I am trying to create using 2 arrays from json data
javascript code
$.ajax({
url: FullURL,
dataType: "JSON",
success: function (data) {
alert(data.hourly.time[1] + "_" + data.hourly.temperature_2m[1]);
// This ex below is from google api document. i want to conver json array into datatable
var data = new google.visualization.DataTable();
data.addColumn('number', 'X');
data.addColumn('number', 'Dogs');
data.addRows([
[0, 0], [1, 10], [2, 23], [3, 17], [4, 18], [5, 9],
[6, 11], [7, 27], [8, 33], [9, 40], [10, 32], [11, 35],
[12, 30], [13, 40], [14, 42], [15, 47], [16, 44], [17, 48],
[18, 52], [19, 54], [20, 42], [21, 55], [22, 56], [23, 57],
[24, 60], [25, 50], [26, 52], [27, 51], [28, 49], [29, 53]
]);

You can use the Array.prototype.forEach() method for this. Array.prototype.forEach() mdn.
The second argument of the callback is the current index of the element. And you can use this index for another array.
const data = new google.visualization.DataTable();
data.addColumn('number', 'Time');
data.addColumn('number', 'Temperature');
const temperatureArray = data.hourly.temperature_2m;
data.hourly.time.forEach((currentTime, index)=>{
data.addRow([currentTime, temperatureArray[index]])
});

Here is how you can convert the JSON input into a grid (array of arrays) using a array .map(), for use in a datatable with data.addRows(grid). The JSON input is reduced to 10 items for this demo:
const input = { "latitude": 42.635273, "longitude": -73.72632, "generationtime_ms": 7.2220563888549805, "utc_offset_seconds": -18000, "timezone": "America/New_York", "timezone_abbreviation": "EST", "elevation": 35.0, "current_weather": { "temperature": -0.1, "windspeed": 3.2, "winddirection": 304.0, "weathercode": 3, "time": "2023-01-21T18:00" }, "hourly_units": { "time": "iso8601", "temperature_2m": "°C" }, "hourly": { "time": ["2023-01-14T00:00", "2023-01-14T01:00", "2023-01-14T02:00", "2023-01-14T03:00", "2023-01-14T04:00", "2023-01-14T05:00", "2023-01-14T06:00", "2023-01-14T07:00", "2023-01-14T08:00", "2023-01-14T09:00"], "temperature_2m": [-0.5, -0.8, -1.2, -1.6, -1.7, -1.6, -1.6, -1.7, -2.1, -2.2] } };
let grid = input.hourly.time.map((val, idx) => [val, input.hourly.temperature_2m[idx]]);
console.log('grid:', grid);
// data.addRows(grid);
Output:
grid: [
[ "2023-01-14T00:00", -0.5 ],
[ "2023-01-14T01:00", -0.8 ],
[ "2023-01-14T02:00", -1.2 ],
[ "2023-01-14T03:00", -1.6 ],
[ "2023-01-14T04:00", -1.7 ],
[ "2023-01-14T05:00", -1.6 ],
[ "2023-01-14T06:00", -1.6 ],
[ "2023-01-14T07:00", -1.7 ],
[ "2023-01-14T08:00", -2.1 ],
[ "2023-01-14T09:00", -2.2 ]
]
It might take some time to get used to functional programming, in this example using .map() instead of a for loop, but functional programming makes code more efficient and readable.
References:
.map(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
Functional programming overview: https://www.freecodecamp.org/news/functional-programming-in-javascript/

Related

How to convert a collection of strings to an array of individual strings

function openOrSenior(data) {
let newArr = []
let userData = [data]
return userData.forEach(data => {
data.map(data => {
let answer = (data[0] >= 55 && data[1] > 7) ? console.log("Senior") : console.log("Open");
return answer
})
})
}
the above function should either display senior or open in this form [ 'Open', 'Senior', 'Open', 'Senior' ]
the outpout i got instead was:
Open
Senior
Open
Senior
an example of what is expected:
input = [[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]]
output = ["Open", "Open", "Senior", "Open", "Open", "Senior"]
You could just map the wanted strings, depending on the values of left an right items of the nested arrays.
function openOrSenior(data) {
return data.map(([l, r]) => l >= 55 && r > 7 ? 'Senior' : 'Open');
}
const data = [[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]];
console.log(openOrSenior(data)); // ["Open", "Open", "Senior", "Open", "Open", "Senior"]
If you would like to use the same code-template that you have provided in the description then you can solve it in this way:
function openOrSenior(data) {
let newArr = []
let userData = [data]
userData.forEach(data => {
data.map(dataInside => {
let answer = (dataInside[0] >= 55 && dataInside[1] > 7) ? "Senior" : "Open"
newArr.push(answer)
})
})
return newArr
}
const data = [[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]];
console.log(openOrSenior(data)); // ["Open", "Open", "Senior", "Open", "Open", "Senior"]
But in above solution, we are performing redundant operations, the better way to solve it will be this one:
function openOrSenior(data) {
return data.map(dataInside => (dataInside[0] >= 55 && dataInside[1] > 7) ? "Senior" : "Open")
}
const data = [[18, 20], [45, 2], [61, 12], [37, 6], [21, 21], [78, 9]];
console.log(openOrSenior(data)); // ["Open", "Open", "Senior", "Open", "Open", "Senior"]

Sorting a 2d array JavaScript by value of both columns

How can I quickly sort a 2d array in JavaScript according to value of both columns?
Array will appear in this format:
[12, 3]
[12, 2]
[54, 43]
[32, 12]
After sorting it should look like this:
[12, 2]
[12, 3]
[32, 12]
[54, 43]
You can use Array.sort and subtract the first items in the nested arrays to determine precedence. If they're equal, subtract the second items.
const arr = [
[12, 3],
[12, 2],
[54, 43],
[32, 12]
]
const res = arr.sort((a,b) => a[0] - b[0] || a[1] - b[1])
console.log(res)

How does the input output tensors work for tensorflowjs layers api

I have a classification problem with 8 inputs and 1 output. I create the below model:
const hidden = tf.layers.dense({
units: 8,
inputShape: [58, 8, 8],
activation: 'sigmoid'
});
const output = tf.layers.dense({
units: 1,
activation: 'softmax'
});
var model = tf.sequential({
layers: [
hidden,
output
]
});
Now when I predict
const prediction = model.predict(inputTensor);
prediction.print();
I expect there to be 1 output value from this prediction, but I get more, how does this work?
These are the shapes
console.log(input.shape) // [1, 58, 8, 8]
console.log(prediction.shape) // [1, 58, 8, 1]
Output looks like this:
[[[[0.8124214],
[0.8544047],
[0.6427221],
[0.5753598],
[0.5 ],
[0.5 ],
[0.5 ],
[0.5 ]],
[[0.7638108],
[0.642349 ],
[0.5315424],
[0.6282103],
[0.5 ],
[0.5 ],
[0.5 ],
[0.5 ]],
... 58 of these
The input.shape [1, 58, 8, 8], corresponds to the following:
1 is the batch size. More on batchsize
58, 8, 8 is the inputShape specified in the entry of the network
Likewise the output.shape [1, 58, 8, 8], corresponds to the following:
1 is still the batch size
58, 8 match the inner dimensions of the inputShape
1 is the last units of the network value.
If only the units values are expected, ie a layer of shape [1, 1], one can remove the inner dimensions by using tf.layers.flatten().
const model = tf.sequential();
model.add(tf.layers.dense({units: 4, inputShape: [58, 8, 8]}));
model.add(tf.layers.flatten())
model.add(tf.layers.dense({units: 1}));
model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
model.fit(tf.randomNormal([1, 58, 8, 8]), tf.randomNormal([1, 1]))
model.predict(tf.randomNormal([1, 58, 8, 8])).print()
// Inspect the inferred shape of the model's output, which equals
// `[null, 1]`. The 1st dimension is the undetermined batch dimension; the
// 2nd is the output size of the model's last layer.
console.log(JSON.stringify(model.outputs[0].shape));
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs#1.1.2/dist/tf.min.js"></script>

Transform JavaScript 2D Array

I am creating a dashboard to show data from various stats. I am using Django and Google Charts for creating graphs. It has been good so far but I am stuck at one particular case.
the model class is-
class Registration(models.Model):
event_type = models.CharField(max_length=80)
date_time = models.DateField()
count = models.IntegerField()
my query is-
Registration.objects.filter(event_type__in=['VHRAssmntCompleted',
'VNAAssmntCompleted',
'NonsmokersDeclrtn',
'MWBAssmntCompleted',
'VHCAssmntCompleted',
'SV Document Uploads',
'PapSmear',
'Mammogram',],
date_time__range=(d3,d1)).order_by('date_time')
I get the data in following format:
[["VHR", "2019-02-1", 23],
["VNA", "2019-02-1", 34],
["PAP", "2019-02-1", 50],
["VHR", "2019-02-2", 92],
["VNA", "2019-02-2", 13],
["PAP", "2019-02-2", 65],
["VHR", "2019-02-3", 192],
["VNA", "2019-02-3", 43],
["PAP", "2019-02-3", 11]]
To create a Combo Chart in need the data in following format(something like python dataframe):
[["date", "VHR", "VNA", "PAP" ],
["2019-02-1", 23,34,50],
["2019-02-2", 92,13,65],
["2019-02-3", 192,43,11]]
I am unable to find a way to do this, either format it using Django ORM query itself or transform using JS.
I need help with what approach should I go.
You could take an object for the column position of the values and collect the data by date and column.
var data = [["VHR", "2019-02-1", 23], ["VNA", "2019-02-1", 34], ["PAP", "2019-02-1", 50], ["VHR", "2019-02-2", 92], ["VNA", "2019-02-2", 13], ["PAP", "2019-02-2", 65], ["VHR", "2019-02-3", 192], ["VNA", "2019-02-3", 43], ["PAP", "2019-02-3", 11]],
cols = { VHR: 1, VNA: 2, PAP: 3 },
result = data.reduce((r, [key, date, value]) => {
var row = r.find(([d]) => d === date);
if (!row) {
r.push(row = [date, 0, 0, 0]);
}
row[cols[key]] = value;
return r;
}, [["date", "VHR", "VNA", "PAP"]]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
you can group them by date, then using Object.entries loop through the grouped result and transform it to [date, "VHR", "VNA", "PAP"]
const data = [
["VHR", "2019-02-1", 23],
["VNA", "2019-02-1", 34],
["PAP", "2019-02-1", 50],
["VHR", "2019-02-2", 92],
["VNA", "2019-02-2", 13],
["PAP", "2019-02-2", 65],
["VHR", "2019-02-3", 192],
["VNA", "2019-02-3", 43],
["PAP", "2019-02-3", 11]
];
const grouped = data.reduce((all, [key, date, value]) => {
all[date] = {
...all[date],
[key]: value
};
return all;
}, {});
const result = ["date", "VHR", "VNA", "PAP"].concat(
Object.entries(grouped).map(([date, obj]) => [date, ...Object.values(obj)])
);
console.log(result);

Get some set of array based on condition from two arrays of array in Javascript

I have two arrays of array in Javascript like
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]];
var array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]];
I want to get the set of arrays from array1 which match the first element of each array of the array2
in my example case both array1 and array2 have array with first element as 10 11 and 12, so it should return
[[10, 2], [11, 4], [12, 30]];
is there any easy and efficient way using pure javscript or lodash, underscor framework or something like that. Without iterate over and match one by one of this two array ?
In ES6, you could use Set.
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
set = new Set(array2.map(a => a[0])),
result = array1.filter(a => set.has(a[0]));
console.log(result);
Version with an object as hash table
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
result = array1.filter(function (a) {
return this[a[0]];
}, array2.reduce(function (r, a) {
r[a[0]] = true;
return r;
}, Object.create(null)));
console.log(result);
You can use lodash _.intersectWith function in order to solve this problem in an inline.
_.intersectionWith(array1, array2, function(a, b) {
return a[0] === b[0];
});
I don't know about performance cos I haven't had the chance to have a look at the source code of this function. Anyway, I like it for its simplicity. Here's the fiddle in case you want to check it out.
If you can make use of Set, then you can compute the a set of numbers to look for first and use .filter to only get the arrays whose first element is in that set:
var haystack = new Set(array2.map(x => x[0]));
var newArray = array1.filter(x => haystack.has(x[0]));
Of course you can also use the lodash or underscore versions of .map and .filter.
Alternatives to using Set would be:
Create an array of numbers instead and use indexOf to test existence. That will scale linearly with the number of elements:
var haystack = array2.map(x => x[0]);
var newArray = array1.filter(x => haystack.indexOf(x[0]) > -1);
Create an object with number -> true entries to test existence with in, hasOwnProperty or just object access:
var haystack = array2.reduce((obj, x) => (obj[x[0]] = true, obj), {});
var newArray = array1.filter(x => haystack[x[0]]);
Which one performs better depends on the number of elements you have and the environment the code is running in.
You can do this with filter() and find()
var array1 = [
[10, 2],
[11, 4],
[12, 30],
[13, 17],
[14, 28]
];
var array2 = [
[8, 13],
[9, 19],
[10, 6],
[11, 7],
[12, 1]
];
var result = array1.filter(function(ar) {
return array2.find(function(e) {
return e[0] == ar[0]
})
})
console.log(result)
I would do this with a Map anf filter combo in ES6 as follows;
var array1 = [[10, 2], [11, 4], [12, 30], [13, 17], [14, 28]],
array2 = [[8, 13], [9, 19], [10, 6], [11, 7], [12, 1]],
m = new Map(array2),
array3 = array1.filter(a => m.has(a[0]));
console.log(array3);
If you need backwards compatibility other answers are pretty good.

Categories

Resources