How to make an array of points using JavaScript? - javascript

I use JavaScript and Chartjs library to draw charts. I store points data in JSON:
"Chart1":{"1": "4","4": "4","10": "4"}
To draw charts correctly I need to provide input like that:
data:[{x:1,y:4},{x:4,y:4},{x:10,y:4}].
I tried do this this way:
var userData = JSON.parse('{"Chart1":{"1": "4","4": "4","10": "4"}}');
var MyKey = [Object.keys(userData['Chart1'])];
var MyVal = [Object.values(userData['Chart1'])];
var POINTS = []; //I tried also {}
for(b=0; b <= MyKey.length; b++)
{
POINTS.push({x:MyKey[b],y:MyVal[b]});
}
and then in config variable:
data:[POINTS]
but the output is:
[
0:
{
x:["1","4","10"]
y:["4","4","4"]
}
1:
{
x:undefined
y:undefined
}
}
f
So how I should do this correctly?
EDIT:
I corrected json string, I pasted it wrong, it's only a typo but thank you all for vigiliance

You can use Object.entries()
var userData = JSON.parse('{ "Chart1":{"1": "4","4": "4","10": "4"} }');
const data = Object.entries(userData['Chart1']).map(([x, y]) => ({ x, y }));
console.log(data);

Some characters were missing from the json string in your example.
Object.keys and Object.values return arrays, don't enclose them in [].
You're storing strings, but your points probably need numbers for x and y. You can do the conversion with a + operator (or parseInt or Number).
var userData = JSON.parse('{"Chart1":{"1": "4","4": "4","10": "4"}}');
var MyKey = Object.keys(userData['Chart1']);
var MyVal = Object.values(userData['Chart1']);
var POINTS = [];
for (b = 0; b < MyKey.length; b++) {
POINTS.push({
x: +MyKey[b],
y: +MyVal[b]
});
}
console.log(POINTS);

You can do this by using Object.entries to get the keyPair value and then map it so that x = key and y = value.
const x = {Chart1:{"1": "4","4": "4","10": "4"}};
const chartKeyValuePair = Object.entries(x.Chart1);
const xy = chartKeyValuePair.map(([key, value]) => {return {x:key, y: value}});
console.log(xy);

You're overcomplicating it! If you use a for...in loop, you get the key of each property in the data, and you can use that to refer to the value. No need for Object.keys etc. Demo:
var userData = JSON.parse('{"Chart1":{"1": "4","4": "4","10": "4"}}');
var POINTS = [];
for (key in userData.Chart1) {
POINTS.push({
x: key,
y: userData.Chart1[key]
});
}
console.log(POINTS);
N.B. You'll see I made an assumption about the real stucture of the userData JSON string, because what you've posted in the question isn't valid JSON and causes a script error.

Related

Processing the data into a desired format in javaScript

I am new to JavaScript and want to process the following array -
var a = [
"John-100",
"Mark-120",
"John-50",
"Mark-130"
]
into the following format -
a = {
"John": [100, 50],
"Mark": [120, 130]
}
But have been unable to do so. Any help will be very much appreciated.
Edit - Any other format ideas where the marks of a particular student can be grouped together are also welcome.
Here is one way to achieve what you described:
var a=[
"John-100",
"Mark-120",
"John-50",
"Mark-130"
]
function convertToSpecialObject(input) {
//setup the output as an empty object
const output = {};
// iterate through input array one element at a time
input.forEach(e => {
// split the current element by dividing it into part[0] before the dash
// and part[1] after the dash sign
const parts = e.split(/-/);
// now check the output object if it already contains a key for the part before the dash
if(!output[parts[0]]) {
// in this case, we don't have a key for it previously
// so lets set it up as a key with an empty array
output[parts[0]] = [];
}
// we must have already created a key or there is a key in existence
// so let's just push the part after the dash to the current key
output[parts[0]].push(Number(parts[1]));
});
// work done
return output;
}
const b = convertToSpecialObject(a);
console.log(b);
you can achieve this by using reduce and split method
var a=[
"John-100",
"Mark-120",
"John-50",
"Mark-130"
]
const b = a.reduce((acc, val) => {
const _split = val.split('-');
const name = _split[0]
if(acc && acc[name]) {
acc[name].push(+_split[1])
} else {
acc[name] = [+_split[1]]
}
return acc;
}, {});
console.log(b)
You can achieve it in a very simple way by just using a Array.forEach() method along with the String.split().
Live Demo :
var a = [
"John-100",
"Mark-120",
"John-50",
"Mark-130"
];
const obj = {};
a.forEach(element => {
if (!obj[element.split('-')[0]]) {
obj[element.split('-')[0]] = [];
}
obj[element.split('-')[0]].push(element.split('-')[1])
});
console.log(obj);
With Simple Approach
const input = [
"John-100",
"Mark-120",
"John-50",
"Mark-130"
];
const getCustomObject = (arr) => {
const obj = {};
for (let i = 0; i < arr.length; i++) {
const split = arr[i].split('-'); //spliting with '-'
if (obj[split[0]]) {
//push to existing array
obj[split[0]].push(split[1]);
} else {
obj[split[0]] = []; //initilize array if no member
obj[split[0]].push(split[1]);
}
};
return obj;
}
console.log(getCustomObject(input));
Now numbers are not numerical values, It can be achieved with parseInt or parseFloat
As I suggested, string split, and array reduce - add in an array map and it's a single line of code
let a=["John-100","Mark-120","John-50","Mark-130"];
a=a.map(v=>v.split('-')).reduce((r,[n,m])=>({...r,[n]:[...r[n]||[],+m]}),{});
console.log(JSON.stringify(a));
The only answer with the correct result ... an array of NUMBERS

count each duplicate value in object and increase

im struggling with following logic.
I am creating following array of objects upon running through a given string.
[{"word":"Frank","c":1},
{"word":"Irina","c":1},
{"word":"Frank","c":1},
{"word":"Frank","c":1},
{"word":"Thomas","c":1}]
what i want to achieve is:
[{"word":"Frank","c":3},
{"word":"Irina","c":1},
{"word":"Thomas","c":1}]
what would be the best way here?
I am sending the string to this function and create the array. but im not able to get what I want.
function words(str) {
return str.split(" ").reduce(function(count, word) {
if(word.length>2&&isLetter(word)){
data.push({word:word, count: 1});
}
}, {});
}
thanks for some help
Adrian
You can use object accumulator to keep count of each word and then using Object.values() get all the values.
function words(str) {
return Object.values(str.split(" ").reduce((result, word) => {
result[word] ??= {word, count: 0};
result[word].count += 1;
return result;
}, {}));
}
console.log(words("Frank Irina Frank Frank Thomas"));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Assuming that c is not always 1 (in which case you can do as the other post suggested and just keep count of the words), you can do it like this, looping through the data and summing the c values in a buffer, using word as the key for the buffer. Then map the buffer values to a final array.
const data = [{"word":"Frank","c":1},
{"word":"Irina","c":1},
{"word":"Frank","c":1},
{"word":"Frank","c":1},
{"word":"Thomas","c":1}];
//console.log(data);
let buffer = {};
data.forEach(i=>{
let w = i.word;
let words = buffer[w] || {word: w, c: 0};
words.c = i.c*1 + words.c;
buffer[w] = words;
});
let final = Object.values(buffer).map(b=>{
return {word: b.word, c: b.c};
});
console.log(final);
This will work for any values of c:
const data = [{"word":"Frank","c":2},
{"word":"Irina","c":4},
{"word":"Frank","c":1},
{"word":"Frank","c":3},
{"word":"Thomas","c":1}];
//console.log(data);
let buffer = {};
data.forEach(i=>{
let w = i.word;
let words = buffer[w] || {word: w, c: 0};
words.c = i.c*1 + words.c;
buffer[w] = words;
});
let final = Object.values(buffer).map(b=>{
return {word: b.word, c: b.c};
});
console.log(final);

construct array back together

My script reads EventSource, and on a message it will get some line data from a variable. That variable will be a array, my script breaks the array down and for each point it flips the x with the y value. It then sends each point as a post request. Is there anyway I can reconstruct the array back together, and then send the post request after flipping each x and y value?
here's my script:
var evtSource = new EventSource("http://URL.com/");
evtSource.onmessage = function(e) {
var obj = JSON.parse(e.data);
var line = JSON.stringify(obj.line)
var line22 = obj.line
//console.log(line22)
line22.forEach(function(point, index){
console.log(JSON.stringify(point)); // console log example// -> "[120,250]"
const [x, y] = point;
console.log(`x: ${x}, y: ${y}`);
var FlipXYvalues = "[[" + y + "," + x + "]]"; // Complies it again... flips the values..
var ident = "String"
if (obj.ident === ident) //the string...
{
$.post("http://URL.com/", {
l: (FlipXYvalues),
w : (obj.lineWidth),
c: (obj.lineColor.replace("#", "")),
o: ("100"),
f: ("1"),
_: ("false")
})
}
});
}
You can use Array#map() to create a new array based on some other array
line22 = [[1,2],[3,4],[5,6],[7,8]];
var newLines = line22.map(point => {
return [point[1], point[0]];
});
//using array destructuring
//if you dont want to mess with specifying indexes
var newLines = line22.map(([x,y]) => {
return [y,x];
});
console.log(JSON.stringify(newLines));
//$.post("http://URL.com/", {l:newLines});

Create nested Javascript Object dynamically

I have got a . (dot) separated string, from which I want to create nested JSON object. The length of the string is not fixed. For example,
var string = 'a.b.c.d';
Then my JSON object should be as following:
a: {
b: {
c:{
d: {
//Some properties here.
}
}
}
}
I've tried following code:
var packageName = "a.b.c.d"
var splitted = packageName.split('.');
var json = {};
for(var i=0;i<splitted.length-1;i++){
json[splitted[i]] = splitted[i+1];
}
But this returns
{
a: 'b',
b: 'c',
c: 'd'
}
But this is not what I want. I've also searched on google and found similar questions, but no solutions answer my problem. For example this.
A good use case for reduce
packageName = "a.b.c.d";
initProps = {hi: 'there'};
obj = packageName.split('.').reduceRight((o, x) => ({[x]: o}), initProps);
console.log(JSON.stringify(obj))
If you find loops easier to work with, a loop could be written concisely as
result = {};
ptr = result;
for (let prop of packageName.split('.'))
ptr = ptr[prop] = {};
You need to create a new object each time and attribute it to the last object created. And it goes until splitted.length, not splitted.length - 1, because you're using <, not <=.
var packageName = "a.b.c.d";
var splitted = packageName.split('.');
var json = {};
var current = json;
for (var i = 0; i < splitted.length; i++) {
current[splitted[i]] = {};
current = current[splitted[i]];
}
console.log(json);
You may use the last splittted part as property for some payload.
I suggest to keep the object reference and use a temporary variable for aceessing an creating a new property, if necessary.
Please avoid the use of JSON for not stringified objects.
var packageName = "a.b.c.d",
splitted = packageName.split('.'),
result = {},
temp = result,
i;
for (i = 0; i < splitted.length - 1; i++) {
temp[splitted[i]] = temp[splitted[i]] || {};
temp = temp[splitted[i]];
}
temp[splitted[i]] = { some: 'data' };
console.log(result);

Convert javascript object keys to real int after JSON encoded

I have this:
var a = {};
a[1] = 1;
a[4] = 4;
console.log(JSON.stringify(a));
then I get:
{"1":1,"4":4}
but I want to get:
{1:1,4:4}
how to reach this? In other words, I want to keys be real int.
When you call JSON.stringify() method it creates a valid JSON string.
One of the rules for valid JSON is that every property should be in "quotes".
So thats why it is impossible to get such result as you want using JSON.stringify.
If you want to just convert such object to array it is possible, for example usin such function.
function numerableObjectToArr(obj) {
var result = [];
var keys = Object.keys(obj);
keys.forEach(function(item){
result.push(obj[item]);
})
return result;
}
var a = {};
a[1] = 1;
a[4] = 4;
numerableObjectToArr(a); // returns [1, 4]
But in this way you will just receive Array with values of existing properties in the obj.
But if your prop name means the index in the array, and you are sure that there will be always number as a prop name - you can improve this function:
function numerableObjectToArr(obj) {
var result = [];
var keys = Object.keys(obj);
keys.forEach(function(item){
result[+item] = obj[item]; //we put index, then we put value to that place in array
})
return result;
}
var a = {};
a[1] = 1;
a[4] = 4;
numerableObjectToArr(a); // returns [undefined, 1, undefined, undefined, 4]
I'm not sure you can do what you're trying to do the as the keys have to be string values. I'd advise having string name for your keys (i.e 1 = One, 2 = Two, etc). You could then try this:
var a = {};
a.one = 1;
a.two = 2;
a.three = 3;
a.four = 4;
console.log(JSON.stringify(a));
I hope this helps.
var a = {};
a[1] = 1;
a[4] = 4;
alert(JSON.stringify(a).replace(/\"([0-9]+)\":/g, '$1:'));
But it is kludge. JSON - has a string keys.

Categories