How do I merge JSON objects into 1 JSON object - javascript

Given:
var result1 = [{'p1':'v1'}];
var result2 = [{'p2':'v2'}];
var array1 = [{'p3':'v3'},{'p4':'v4'}];
Rules:
If array has one property, add property to main array to return.
If array has multiple properties, add a label and keep array as is.
https://jsfiddle.net/3unx0hsa/5/
function mergeJson(data) {
let newarray1 = [];
for (let index = 0; index < resultsArray.length; index++) {
let element = resultsArray[index][0];
if (element.length === 1) {
newarray1.push(element);
}
if (element.length > 1) {
var x = `{data${index}: ${element}`;
newarray1.push(x);
}
}
}
Illustration:

Template string literal creates a string. You need an object literal instead
var x = {[`data${index}`]: element};
var result1 = [{'p1': 'v1'}];
var result2 = [{'p2': 'v2'}];
var array1 = [{'p3': 'v3'}, {'p4': 'v4'}];
let x = mergeJson([result1, result2, array1]);
console.log(x);
function mergeJson(resultsArray) {
let newarray1 = [];
for (let index = 0; index < resultsArray.length; index++) {
let element = resultsArray[index];
if (element.length === 1) {
newarray1.push(element[0]);
}
if (element.length > 1) {
var x = {[`data${index}`]: element};
newarray1.push(x);
}
}
return newarray1;
}

After this line: var x = `{data${index}: ${element}`;, the value for x is a string. That is what you are seeing in you output. Change that line to something like this:
var x = {`{data${index}`: element};
That should give you the result you're expecting.

Using that type of function you will be able to display Json values
//JSON = objects and you have to call them for examle:
var result1 = [{'p1':'v1'}];
var result2 = [{'p2':'v2'}];
var array1 = result1.concat(result2);
for (i in array1){
array1[i];
for(x in array1[i]){
document.getElementById("test").innerHTML += x+" - "+array1[i][x] +" <br>";
}
}
<div id="test"></div>

Related

String to array - split returning NaN value | Javascript

I want to convert a string into an array. that works only with number value. in the following example the "border_color & border_style keys" returning NaN as value.
var str ="margin_top=5&margin_bottom=5&border_color=#dfdfdf&border_style=solid";
strToArray(str);
function strToArray(str){
str = str.replace(/\(|\)/g,'');
var arr = str.split('&');
var obj = {};
for (var i = 0; i < arr.length; i++) {
var singleArr = arr[i].trim().split('=');
var name = singleArr[0];
var value = singleArr[1]-0;
if (obj[name] === undefined) {
obj[name] = value;
}
alert(name+': '+value);
}
return obj;
}
The NaNs are comming from trying to convert the non-numeric values into numbers (ie, "#dfdfdf" and "solid"). Before trying to convert to numbers, check if the value string is valid or not using isNaN:
var value = singleArr[1]; // don't convert yet
if (obj[name] === undefined) {
obj[name] = isNaN(value)? value: +value; // if value is not a valid number, then keep it as it is (a string). Otherwise, convert it to a number (using unary + which is shorter than substracting 0)
}
Working example:
var str ="margin_top=5&margin_bottom=5&border_color=#dfdfdf&border_style=solid";
strToArray(str);
function strToArray(str){
str = str.replace(/\(|\)/g,'');
var arr = str.split('&');
var obj = {};
for (var i = 0; i < arr.length; i++) {
var singleArr = arr[i].trim().split('=');
var name = singleArr[0];
var value = singleArr[1];
if (obj[name] === undefined) {
obj[name] = isNaN(value)? value: +value;
}
alert(name+': '+value);
}
return obj;
}
Not really sure the way you want to return, but you can use: Object.values()
var str ="margin_top=5&margin_bottom=5&border_color=#dfdfdf&border_style=solid";
strToArray(str);
function strToArray(str){
str = str.replace(/\(|\)/g,'');
var arr = str.split('&');
var keys = []
var values = []
var obj = {};
for (var i = 0; i < arr.length; i++) {
var singleArr = arr[i].trim().split('=');
keys.push(Object.values(singleArr)[0])
values.push(Object.values(singleArr)[1])
}
alert(values)
alert(keys)
return obj;
}

Return multiple lines instead of console.log

I have the following code that produces the output I need using console.log
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
for(i = 0; i < productId.length; i++) {
console.log(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
}
product()
console.log result -
1234|543210|id1|product1|10
1234|543210|id2|product2|20
1234|543210|id3|product3|30
1234|543210|id4|product4|40
When changing console.log to return, only the first line is returned. return result -
1234|543210|id1|product1|10
Is there a way to return the same results as console.log?
You would usually push the lines to an array and return the array
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var ret = [];
for(i = 0; i < productId.length; i++) {
ret.push(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
return ret;
}
let data = product();
console.log(data); // array holding the lines
// or join it with a newline
console.log(data.join("\n")); // lines as string
Push the results into an array then use the Array#join function.
function product() {
const advertiserId = 1234;
const ord = 543210;
const productId = "id1|id2|id3|id4".split("|");
const productName = "product1|product2|product3|product4".split("|");
const productItemPrice = "10|20|30|40".split("|");
const results = [];
for (let i = 0; i < productId.length; i++) {
results.push(`${advertiserId}|${ord}|${productId[i]}|${productName[i]}|${productItemPrice[i]}`);
}
return results;
}
const data = product();
console.log(data.join('\n'));
You could also use other console commands:
console.dir(data);
When you return from a function, it won't continue to execute. In your case, you can store each result and return them all at once.
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var results = [];
for(i = 0; i < productId.length; i++) {
results.push(advertiserId + "|" + ord + "|" + productId[i] + "|" + productName[i]+ "|" +productItemPrice[i]);
}
return results;
}
results is now an array of strings that you can do what you want with.
Write the output to a variable then return. using return inside the loop will exit the loop
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var output = "";
for(i = 0; i < productId.length; i++) {
output += advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i] + "\n";
}
return output;
}
product()
I think what you need is to store every result of the iteration on a variable, and then after the for loop you return it. Like
var a;
for loop... {
a += (all of your stuff) + '\n'
}
return a;
This should keep the break lines into the variable and so keep the indentation you want like console.log but into a variable.
If you need to have separated values you could store every line into a array and return the array after the for loop.
A return statement stops the function immediately and can only return a single value. You can add up data in the loop and then return at the end.
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
var result = [];
for(i = 0; i < productId.length; i++) {
result.push(advertiserId+"|"+ord+"|"+productId[i]+"|"+productName[i]+"|"+productItemPrice[i]);
}
return result;
}
product()
Can map() the values into an array and return the array or array joined to string
function product() {
var advertiserId = 1234;
var ord = 543210;
var productId = "id1|id2|id3|id4".split("|");
var productName = "product1|product2|product3|product4".split("|");
var productItemPrice = "10|20|30|40".split("|");
return productId.map(function(id, idx) {
return [
advertiserId,
ord,
productId[idx],
productName[idx],
productItemPrice[idx]
].join('|')
}).join('\n')
}
console.log(product());

Javascript: Adding final element to array after for loop completes

Explanation of Desired Results
My source is over 30,000 lines of very structured text with incrementing front numbers followed by incrementing back numbers and separated by a colon. Stripping out the non-essentials, I am left with the following sourceArray, truncated for convenience :)
sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
I am trying to count how many back numbers for each front number and push that to an array. In pseudocode, my final results should look like this:
myArray[totalNumberOf_001_Items, totalNumberOf_002_Items, totalNumberOf_003_Items]
Which in my simple example should give me a final value of:
[3, 2, 2]
Problem and Question
My for loop ends at the end of my data and I am therefore one element short in my array.
How do I make an "extra pass" through the loop or is there another way to get the final element pushed to my array?
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"
];
var myArray = [];
var frontCounter = 1;
var backCounter = 1;
for (var i = 0; i < sourceArray.length; i++) {
var text = sourceArray[i];
var front = text.substr(0, 3);
front = Number(front);
var back = text.substr(4, 3);
back = Number(back);
if (front == frontCounter) {
backCounter++;
} else {
myArray.push(backCounter - 1);
backCounter = 2;
frontCounter++;
}
}
console.log(myArray); // result [3, 2]
You could use an object like below to keep track of how many times the the piece of text appear, the text would be the keys and as value the number of times they appear. From that you can build you array
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
var frontEncounters = {};
function updateFrontEncounters(frontEncounters, front){
var keys = Object.keys(frontEncounters);
if(keys.indexOf(front) == -1)
{
frontEncounters[front] = 1;
}
else
{
frontEncounters[front] += 1;
}
}
for(var item in sourceArray){
var text = sourceArray[item];
var front = text.substr(0, 3);
var back = text.substr(4, 3);
updateFrontEncounters(frontEncounters, front);
}
var keys = Object.keys(frontEncounters);
var myArr = [];
for(var key in keys)
{
myArr.push(frontEncounters[keys[key]])
}
console.log(myArr);
Use an object to store the "front" numbers along with their count.
for (var i = 0; i < sourceArray.length; i++) {
var num = sourceArray[i].slice(0,3);
counts[num] = counts[num] ? counts[num]+1 : 1;
}
Once done, you can very easily convert that to an array:
var result = Object.keys(counts).map(function (key) {
return counts[key];
});
With ES-2017, it is even easier:
var result = Object.values(counts)
Working Snippet:
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"];
var counts = {};
for (var i = 0; i < sourceArray.length; i++) {
var num = sourceArray[i].slice(0,3);
counts[num] = counts[num] ? counts[num]+1 : 1;
}
console.log(counts);
var result = Object.keys(counts).map(function (key) {
return counts[key];
});
console.log(result);
// ES-2017
//console.log(Object.values(counts));
Here's an alternative that you can use so that you don't have to go through the entire source of lines (30,000) . Use a while loop so that you can break as soon as you reach a 0; use Map to store the unique number by making the index/frontnumber the key and make its value an object that serves as a counter to keep track of it's total. If the key exists, update the total; if it doesn't, create a new counter object. Then just return the Map by transforming it into the desired array by map'ing it to an array with only the totals.
var sourceArray = ["001:001", "001:002", "001:003",
"002:001", "002:002",
"003:001", "003:002"
];
function getTotal(sourceArray) {
let count = new Map();
let update = item => count.get(item).total++;
let create = item => count.set(item, {total: 1});
const getItem = index => {
let text = sourceArray[index];
return text.substr(0, 3);
}
let index = -1;
let start = 0;
while (index != 0 && start < sourceArray.length) {
index = getItem(start++);
count.has(index) ? update(index) : create(index);
}
return [...count.values()].map(item => item.total);
}
console.log(getTotal(sourceArray));

Push different object in an array with a for loop

I have an element structured like this:
Element ->
[{values: arrayOfObject, key:'name1'}, ... ,{values: arrayOfObjectN, key:'nameN'}]
arrayDiObject -> [Object1, Object2, ... , ObjectN] //N = number of lines in my CSV
Object1 -> {x,y}
I have to take data from a big string:
cityX#substanceX#cityY#substanceY#
I thought to make it this way, but it seems like it pushes always in the same array of objects. If I put oggetto = {values: arrayDateValue, key: key}; inside the d3.csv function, instead if I put outside the function it add me only empty objects.
Here is my code:
var final = new Array();
var oggetto;
var key;
function creaDati() {
var newdate;
var arrayDateValue = new Array();
var selString = aggiungiElemento().split("#");
//selString is an array with selString[0]: city, selString[1]: substance and so on..
var citySelected = "";
var substanceSelected = "";
for (var i = 0; i < selString.length - 1; i++) {
if (i % 2 === 0) {
citySelected = selString[i];
} else if (i % 2 !== 0) {
substanceSelected = selString[i];
key = citySelected + "#" + substanceSelected;
d3.csv("/CSV/" + citySelected + ".csv", function(error, dataset) {
dataset.forEach(function(d) {
arrayDateValue.push({
x: d.newdate,
y: d[substanceSelected]
});
});
});
oggetto = {
values: arrayDateValue,
key: key
};
arrayDateValue = [];
final.push(oggetto);
}
}
}
Any idea ?
First you should make the if statement for the city and then for the key, which you seem to be doing wrong since you want the pair indexes to be the keys and the not pair to be the city, and you are doing the opposite. And then you need to have the d3.csv and push the objects outside of the if statement, otherwise in your case you are just adding elements with citySelected="".
Try something like :
for(var i = 0; i < selString.length -1; i+=2){
cittySelected = selString[i];
substanceSelected = selString[i+1];
key = citySelected + "#" + substanceSelected;
d3.csv("/CSV/"+citySelected+".csv", function(error, dataset){
dataset.forEach(function(d){
arrayDateValue.push({x: d.newdate, y: d[substanceSelected]});
});
});
oggetto = {values: arrayDateValue, key: key};
arrayDateValue = [];
final.push(oggetto);
}
It's is not the best way to do it, but it is clearer that what you are following, i think.
In the if(i % 2 == 0) { citySelected = ... } and else if(i % 2 !== 0) { substanceSelected = ... } citySelected and substanceSelected will never come together.
The values should be in one statement:
if(...) { citySelected = ...; substanceSelected = ...; }
The string can be splitted into pairs
city1#substance1, city2#substance2, ...
with a regex (\w{1,}#\w{1,}#).
Empty the arrayDateValue after the if-statement.
Hint:
var str = "cityX#substanceX#cityY#substanceY#";
function createArr(str) {
var obj = {};
var result = [];
var key = "";
// '', cityX#substanceX, '', cityYsubstanceY
var pairs = str.split(/(\w{1,}#\w{1,}#)/g);
for (var i = 0; i < pairs.length; i++) {
if(i % 2 !== 0) {
key = pairs[i];
// d3 stuff to create values
obj = {
// Values created with d3 placeholder
values: [{x: "x", y: "y"}],
// Pair
key: key
};
result.push(obj);
}
// Here should be values = [];
}
return result;
}
var r = createArr(str);
console.log(r);
May be you can do like this;
var str = "cityX#substanceX#cityY#substanceY",
arr = str.split("#").reduce((p,c,i,a) => i%2 === 0 ? p.concat({city:c, key:a[i+1]}) : p,[]);
console.log(JSON.stringify(arr));
RESOLVED-
The problem is about d3.csv which is a asynchronous function, it add in the array when it finish to run all the other code.
I make an XMLHttpRequest for each csv file and it works.
Hope it helps.

How to count the JSON object and on the basis of count take the same output

How to count the JSON object and on the basis of count take the same output
var obj =
[
{"id":"0","name":"Mike Johnson","group":1},
{"id":"1","name":"Bob Smith","group":2},
{"id":"2","name":"Richard Thomas","group":3},
{"id":"3","name":"Betty White","group":16},
{"id":"4","name":"Tim Thompson","group":3},
{"id":"5","name":"Carl Lewis","group":16},
{"id":"6","name":"Kathy Towers","group":3},
{"id":"7","name":"Billy Bob","group":1},
{"id":"8","name":"Sally Bailey","group":1}
];
First I would like the count after it on the basis of count. I want same output like input.
for Count:-
var count = 0;
function getCount() {
for (var i = 0; i < obj.length; i++) {
count++;
}
return count;
}
for output :-
function showDetails() this is not giving the proper output
{
for(var j=0; j< count; j++){
obj.push([{j}]);
}
alert(obj.name);
}
alert(showDetails());
And I want an output like:-
var obj =
[
{"id":"0","name":"Mike Johnson","group":1},
{"id":"1","name":"Bob Smith","group":2},
{"id":"2","name":"Richard Thomas","group":3},
{"id":"3","name":"Betty White","group":16},
{"id":"4","name":"Tim Thompson","group":3},
{"id":"5","name":"Carl Lewis","group":16},
{"id":"6","name":"Kathy Towers","group":3},
{"id":"7","name":"Billy Bob","group":1},
{"id":"8","name":"Sally Bailey","group":1}
];
Can anybody help me please?
var data ="January,February,March,April,May,June,July,August,September,October";
var obj = data.split(',').map((item)=>{
return {
name:item
}
});
obj will be the desired output
var str = "January,February,March,April,May,June,July,August,September,October";
var arr = str.split(',').map(function(v) {
return {name: v};
});
console.log(arr);
var str = "January,February,March,April,May,June,July,August,September,October";
var months = str.split(",");
var result = [];
for (i in months)
{
var month = {};
month.name = months[i];
//you can do more things else here, for example:
//month.monthOfYear = (i+1);
//month.numberOfDay = 123123123;
result.push(month);
}
You can do something like this:
var array = string.split(",");
var finalArray = [];
array.forEach(function(item){
var obj = {
name: item
}
finalArray.push(obj);
});
console.log(finalArray);
MDN reference
use var array = string.split(',');
For a more ES2015 heavy version. Constants, arrow function and implicit return statement.
const str = 'January,February,March,April,May,June,July,August,September,October'
const result = str.split(',').map(name => ({name}))
console.log(result)

Categories

Resources