I am getting extra x value in array object using javascript - javascript

I am actually trying to display canvas.js chart using this json dynamically.
I have this result:
[{"s":40,"ProductName":"yoga pants"},
{"s":20,"ProductName":"trousers"},{"s":16,"ProductName":"shirts"},
{"s":10,"ProductName":"pants"},{"s":7,"ProductName":"RED"},
{"s":5,"ProductName":"Tank Top"}]
…which is a json string
I am getting this:
[{40: "yoga pants", x: 0},
{20: "trousers", x: 1},
{16: "shirts", x: 2},
{10: "pants", x: 3},
{7: "RED", x: 4},
{5: "Tank Top", x: 5}]
But i do not want this extra x: value. I am using this code:
var result1 = JSON.parse(result);
var reformattedArray = result1.map(function (o)
{
var obj = {};
obj[o.s] = o.ProductName;
return obj;
});
Thanks in advance

It appears to me that what is really happening is that your reformattedArray is fine, but you are subsequently piping it through charting software that is assigning the x: property, effectively indexing your data for the x axis of a chart.
Is it possible that the result you are reporting is not the result of your map, but rather the result of an additional step?

Related

javascript Array.push({y: yValue, label: myLabel}) setting random "x" key value

I am trying to create an canvasJS, JavaScript Bar Charts, with the following functions,
var dataPoints = [];
var headers;
var groups = [];
var cityWide = 0;
var chart = createChart();
function createChart(title = "Hospitalized Count") {
return new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
title:{
text:"Coronavirus Data in NYC Boroughs"
},
axisX:{
interval: 1
},
axisY2:{
interlacedColor: "rgba(1,77,101,.2)",
gridColor: "rgba(1,77,101,.1)",
title: "Total number of "+title
},
data: [{
type: "bar",
name: "companies",
axisYType: "secondary",
color: "#014D65",
dataPoints: dataPoints
}]
});
}
I am using this function below to set the dataPoints array:
function call: dataPoints = setDataPoints(4)
function setDataPoints(value){
let temp = [];
for(var i = 0; i<groups.length;i++){
if(groups[i][0] == "Citywide"){
continue;
}
yValue = groups[i][value];
myLabel = groups[i][0];
console.log("y: "+ yValue);
console.log("label: "+ myLabel);
temp.push(
{
y: yValue,
label: myLabel
});
}
console.log(temp);
return temp;
}
But when i console.log(dataPoints) I am getting this:
[
{"y": "136319","label": "Bronx","x": 0},
{"y": "202778","label": "Brooklyn","x": 1},
{"y": "97006","label": "Manhattan","x": 2},
{"y": "202737","label": "Queens","x": 3},
{"y": "54479","label": "StatenIsland","x": 4}
]
the expected result for dataPoints should be as follows:
[
{y:136319, label: "Bronx" },
{y:202778, label: "Brooklyn" },
{y:97006, label: "Manhattan" },
{y:202737, label: "Queens" },
{y:54479, label: "StatenIsland" }|
]
When I tried to set x
temp.push(
{
x: "123",
y: yValue,
label: myLabel
});
or delete temp[i]['x'] it doesn't work.
As you may of notice the x value are the indexes of the array, I have no idea why its being set and how do I even remove.
I have tried
dataPoints = temp;
console.log(dataPoints[0].hasOwnProperty('x'));
and returns false
Any help would appreciate it thanks in advance!
EDIT based of comment:
in for loop:
console.log(temp[i]['x']) returns undefined
If I add in to temp.push({ x: "123", ...})
console.log(temp[i]['x']) returns 123
console.log(temp[i]):
{y: "54479", label: "StatenIsland"}
label: "StatenIsland"
x: 4
y: "54479"
__proto__: Object
function.js:98
I'm not familiar with CanvasJS but my guess is that it's mutating the dataPoints array you give it to fill in the 'x' coordinate on the chart. console.log doesn't run synchronously, so by the time you see the output it's already been mutated.
If you console.log([...dataPoints]) or console.log([...temp]) I bet the x won't be there.
According to the API docs for dataPoints.x:
If not provided, it will be set automatically set according to its index position on dataPoints Array.
If you want to keep your "clean" copy of dataPoints you need to pass a copy of the array to the chart [...dataPoints].

How to insert a object in an array (as a element )

I am from C++ background.
I am trying to translate a C++ code to JavaScript.
in C++ we have vector < pair < int,int > > to store pairs.
in JS i have a situation. i want to store 2D coordinates. i actually want to push new coordinates to the array.
i did like
first I created a Object
const coordinate = {
x= 9,
y= 10
}
Then i tried to push that object into the array CoordinateStorage that i want this object to get stored
CoordinatesStorage.unshift({X : coordinate.x, Y : coordinates.y});
I know this code shown above is absolutely wrong to store an object into the array. I searched out for sources but i got nothing useful.
Please recommend some sources that i can refer for such translation related problems if possible.
Generally speaking, we should use the .push method for an array.
There are other methods available you can find them here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array but the .push method for your case is more suitable.
Basically, as a result, we want to have something like this:
[ {x: 2, y: 4 }, { x: 2, y: 4 } ] We have an array of objects.
Or we could also have an array of arrays:
[[1, 2], [3, 4], [4, 6]] Not sure if it okay for your case, but maybe as an option.
Also, we could create a class Vector and we might have something like
[ Vector { x: 1, y: 2 }, Vector { x: 3, y: 4 }, Vector { x: 4, y: 6 } ]
Let's take a look at the examples:
Using the plain object for the vector:
const coordinate1 = {
x: 2,
y: 4
};
const coordinate2 = {
x: 3,
y: 4
};
const coordinatesStorage = [];
coordinatesStorage.push(coordinate1);
coordinatesStorage.push(coordinate2);
If you will do console.log(coordinatesStorage) you will see [ { x: 2, y: 4 }, { x: 3, y: 4 } ]
Using the array to store a vector:
const coordinate1 = [1, 2];
const coordinate2 = [3, 4];
const coordinatesStorage = [];
coordinatesStorage.push(coordinate1);
coordinatesStorage.push(coordinate2);
The coordinatesStorage will be [ [ 1, 2 ], [ 3, 4 ] ]
Using the Vector class:
Maybe in your case, it would be more helpful to operate with a class Vector:
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
const coordinatesStorage = [];
coordinatesStorage.push(new Vector(1, 2));
coordinatesStorage.push(new Vector(3, 4));
coordinatesStorage.push(new Vector(4, 6));
And here in the console you will see [ Vector { x: 1, y: 2 }, Vector { x: 3, y: 4}, Vector { x: 4, y: 6 } ]
Take a look at the Vector implementations in JS:
https://gist.github.com/jjgrainger/808640fcb5764cf92c3cad960682c677
https://github.com/maxkueng/victor/blob/master/index.js
I hope this helps. Good luck!
First initialize the array
var CoordinatesStorage = [];
//create object
const coordinate = {
x: 9, // Note - the operator is colon : not = as in the question
y: 10
}
// push to array
CoordinatesStorage.push(coordinate);
Now your array will be like this [{x:9, y:10}] if you push again the array will be [{x:9, y:10}, {x:9, y:10}]
Tip: Arrays are denoted by square brackets eg: ['math', 'science', 'english']
Objects are denoted by key-value pairs wrapped in curly brackets
eg: var student = {
name: "John", // string value
age: 6, // integer value
sex: "M",
phone: [123456789 , 564654654] // value is of array of 2 items
}

Replacing javascript random number generator with my own JSON

I'm trying to show my data in a D3 graph. I've followed the tutorial and end up at this bit of code:
// 8. An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
var dataset = d3.range(n).map(function(d) {
return {
"y": d3.randomUniform(1)()
}
})
Instead of randomly generating numbers, I want to feed in my own JSON data. This is what I tried:
var obj = {
y: "1",
y: "6",
y: "10"
};
var dataset = JSON.stringify(obj);
However, when I do this it doesn't work. For comparison this is what the old code spat out (from console.log):
0: {y: 0.8863000631639524}
1: {y: 0.730344915698621}
2: {y: 0.23216952106703048}
3: {y: 0.6065558075691728}
This is what my new code spits out:
(3) [{…}, {…}, {…}]
(index):119 {"y":"10"}
d3.v5.min.js:2 Error: <path> attribute d: Expected number, "M0,NaNC0,NaN,0,NaN,…".
The complete code is here around line 41:
http://jsfiddle.net/spadez/mt1rngqo/13/
dataset is an array of objects that each have a field y that is a number, not a string
var dataset = [
{y: 1},
{y: 6},
{y: 10}
];
//var dataset = JSON.stringify(obj);
console.log(dataset);

Better way to convert JSON to arrays for graphing timeseries in C3?

I'm working on converting some JSON data into a format that will work for graphing a timeseries in C3, which takes an array of arrays as column input. I have my unique x values array, but I can't figure out a great way to get my y values. Once I get this done, I need to add y2 with numSold, but I think if I can solve this, I'll be able to figure that part out.
This is the final format I need for the data:
[
["x", "9-2-17", "9-4-17", "10-2-17"],
['item1-cost', 100, 150, 10],
['item3-cost', 200, null, 20],
...
]
There isn't a set number of dates or set number of items. It's whatever I read from the database. The item numbers aren't necessarily consecutive. We only care about graphing the data for items we have data for. But there won't be data for every date-item combination. When that happens, I need to insert a null to indicate that the item didn't have data for that date. Item numbers are 1-indexed.
I'm fine with using anything from lo-dash or D3 in addition to the plain JavaScript functions to solve this, but I'm trying to avoid hard to read code and inefficient code. I feel like others must have had a need for this and that there must be some sort of function like maybe a filter function that I should be using instead.
My current implementation is not as efficient as I'd like and is a bit hard to read. I'm using the item number as an index and making a sparse array that I'll have to condense later. Here's the psudocode:
For every d object in data
For the i index of d.date in uniqueDates
If values[d.item] is undefined
Fill values[d.item]] with null for uniqueDates.length
Set values[d.item][i] to d.cost
Convert values to dense format for graphing
Here's a link to the Fiddle I'm playing with:
https://jsfiddle.net/dbkidd/q3r3moqu/
var data = [
{date: '9-2-17', item: 1, cost: 100},
{date: '9-2-17', item: 3, cost: 200},
{date: '9-4-17', item: 1, cost: 150},
/* '9-4-17' does not have an entry for item 3 so cost should be counted as null */
{date: '10-2-17', item: 1, cost: 10},
{date: '10-2-17', item: 3, cost: 20}
]
var uniqueDates = _.uniq(_.flatMap(data, 'date'));
uniqueDates.unshift('x');
var values = [];
values.push(uniqueDates);
function getLabel(index) {
return 'item' + index + '-' + 'cost';
}
for (var d = 0; d < data.length; d++) {
var i = _.indexOf(uniqueDates, data[d].date);
if (data[d].item !== undefined) {
var item = data[d].item;
if (values[item] === undefined) {
values[item] = _.fill(Array(uniqueDates.length), null);
values[item][0] = getLabel(item);
}
values[item][i] = data[d].cost;
}
}
function checkIfUndefined(x) {
return (x !== undefined);
}
function sparseToDense(data) {
return data.filter(checkIfUndefined);
}
values = sparseToDense(values);
I was intrigued by this problem and came up with a first version. It's a little different than yours but here it is. I will note that I didn't try to sort the dates or rename the items to something useful but those can be added.
var data = [
{date: '9-2-17', item: 1, cost: 100},
{date: '9-2-17', item: 3, cost: 200},
{date: '9-4-17', item: 1, cost: 150},
/* '9-4-17' does not have an entry for item 3 so cost should be counted as null */
{date: '10-2-17', item: 1, cost: 10},
{date: '10-2-17', item: 3, cost: 20},
{date: '10-3-17', item: 2, cost: 2000}
]
// utility functions
const product = (...sets) =>
sets.reduce((acc, set) =>
_.flatten(acc.map(x => set.map(y => [ ...x, y ]))),
[[]]);
// the meat and potatoes
const builder = lookup => pairs => pairs.reduce((agg, [item, date]) => {
const out = _.cloneDeep(agg);
const value = _.get(lookup, [date, item, 'cost'], null);
const evalue = _.get(out, date, []);
evalue.push(value);
_.set(out, date, evalue);
return out;
}, {})
// setup data structures for searching
const byDateByItem = _.mapValues(_.groupBy(data, 'date'), x => _.keyBy(x, 'item'));
const items = _.uniq(data.map(x=>x.item));
const dates = _.uniq(data.map(x=>x.date));
// create all posibilities
const pairs = product(items, dates);
// populate possibilities with values
const hash = builder(byDateByItem)(pairs);
// put keys with values in their respective lists
const p = _.toPairs(hash).map(_.flatten);
// smash data into a matrix type thing
const table = [['x',...items], ...p];
// flip the table on it's side (╯°□°)╯︵ ┻━┻
const out = _.zip(...table);
console.log('out', out);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Javascript Map function does not preserve the original object

I have a scenario wherein i have
var data = [
{
"x": 1,
"y": 0.27,
"classifier": 1
},
{
"x": 2,
"y": 0.88,
"classifier": 1
}
]
I want another object data2 with y=1-y, which i obtain with:
var data2 = data.map(function(el) {el.y = 1-el.y; return el});
data2[0]
Object {x: 1, y: 0.73, classifier: 1}
data2[1]
Object {x: 2, y: 0.12, classifier: 1}
which is the correct form that i want the data in. However the issue is i want to preserve the original data as well. Right now even data has mutated data.
data[0]
Object {x: 1, y: 0.73, classifier: 1}
data[1]
Object {x: 2, y: 0.12, classifier: 1}
Is map the right function to use here? Am i using it correctly?
While creating a new array, you let its values point to the original objects, which you mutate by assigning to their object properties.
Instead you could also create (shallow) copies of the objects with Object.assign:
var data2 = data.map(function(el) {
return Object.assign({}, el, { y: 1-el.y });
});
Or with arrow function:
var data2 = data.map( el => Object.assign({}, el, { y: 1-el.y }) );
var data = [
{
"x": 1,
"y": 0.27,
"classifier": 1
},
{
"x": 2,
"y": 0.88,
"classifier": 1
}
]
var data2 = data.map( el => Object.assign({}, el, { y: 1-el.y }) );
console.log (data);
You're modifying the original element object, which isn't a full deep copy of the original data.
Create a copy of el in the function and then calculate the new .y. For example:
var data2 = data.map(function(el) {
return {
x : el.x,
y : 1-el.y,
classifier : el.classifier
};
});

Categories

Resources