const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
const loop = (a) => {
for (let j = 0; j < a.length; j++) {
console.log(a[j].url);
}
return;
}
for (let i in obj) {
console.log(i + " " + loop(obj[i]));
}
The output is:
"youtube.com"
"facebook.com"
"urls undefined"
Why does the loop function get executed first? It should only run inside the second loop:
for(let i in obj){
console.log(i + " " + loop(obj[i]) );
}
I want to be able to output:
urls : youtube.com reactjs,javascript
With short code often the easiest thing to do to debug it is to just do a basic walkthrough of your code by hand to see if it's really doing what you want it to.
You'll notice that the second loop simply performs:
console.log("urls" + " " + loop(obj["urls"]) );
This will result in loop being called:
console.log(obj["urls"][0].url);
console.log(obj["urls"][1].url);
return; // returns undefined
Which will output:
youtube.com
facebook.com
Only then (after the first two logs from inside the loop call) will the initial console.log take place with the return value of loop:
console.log("urls" + " " + undefined /*loop(obj["urls"])*/ );
Giving your last line of output:
urls undefined
As for why loop gets called before the console.log("urls" + ...), think about it, how can console.log know what to output, if to output it it needs to have called loop? loop has to come first.
It sounds like you were trying to do something like this:
const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
// Constructs a string representation of the list of categories
const loop = (a) => {
o = "";
for (let j = 0; j < a.category.length; j++) {
o += "," + a.category[j];
}
return o.substring(1);
}
// Call loop for each url in obj
for (let i in obj.urls) {
console.log("urls : " + obj.urls[i].url + " " + loop(obj.urls[i]));
}
This can be tidied up using join instead of your loop function and by using Array.prototype.forEach:
const obj = {
"urls": [{
"url": "youtube.com",
"category": ["react js", "javascript"]
},
{
"url": "facebook.com",
"category": ["react js", "javascript"]
}
]
}
// Call loop for each url in obj
obj.urls.forEach(urlObj => {
console.log("urls : " + urlObj.url + " " + urlObj.category.join(","));
});
Related
I'm very new with coding javascript and also with json data.
I have this code and first of all i want to Group by "week" but i only want to sum the column "resultat"
The column "Start" do i want to show the first value, and in the column "Slut" i want to show the latest value.
Is this possible? And if, do anyone have any suggestions how?
As i sad i'm really new so i'm totaly lost :)
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
var request = new XMLHttpRequest();
request.open("GET", "/weekresult.json", false);
request.overrideMimeType("application/json");
request.send(null);
var jsonData, i, j, x = "";
var jsonData = JSON.parse(request.responseText);
console.log(jsonData);
x += "<table style='border:1px SOLID black;'>";
x += "<tr><th style='background:silver;'>Vecka</th><th style='background:silver;'>Öppning</th><th style='background:silver;'>Stängning</th><th style='background:silver;'>Resultat</th><th style='background:silver;'>Procent</th></tr>";
for (i in jsonData.vecka) {
x += "<tr>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].week + "</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].start + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].slut + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].resultat + " SEK</td>";
x += "<td style='text-align:center;width:20%;'>" + jsonData.vecka[i].procent + "%</td>";
x += "</tr>";
}
x += "</table>";
document.getElementById("demo").innerHTML = x;
</script>``
This is the code that does what you are looking for. It does not generate any DOM Elements, however it takes care of all the logic except for "percent" as you did not specify what is supposed to happen to that value.
To summarize:
Create an Array that holds all the "groups"
Fill that Array with the grouped weeks. If a week is already tracked, add its value to the tracking objects data-Array, else create a new Group.
Now just iterate through every group, display the groups week value and perform the logic to finding the min (start), max (slut) and summed (resultat) values. All of that can be done with the reduce method.
Log/Display the results.
const { vecka } = { "vecka": [{ "week": "20-15", "start": 1000, "slut": 1019, "resultat": "19", "procent": "1.90" }, { "week": "20-15", "start": 1019, "slut": 1036, "resultat": "17", "procent": "1.67" }, { "week": "20-15", "start": 1036, "slut": 1060, "resultat": "24", "procent": "2.32" }, { "week": "20-15", "start": 1060, "slut": 1090, "resultat": "30", "procent": "2.83" }, { "week": "20-16", "start": 1090, "slut": 1121, "resultat": "31", "procent": "2.84" }] };
const sets = [];
for (let set of vecka) {
// Find week if it is already tracked
const trackedWeek = sets.filter(w => w.time == set.week)[0];
if (!trackedWeek) {
// If week is not already being tracked, create a new entry
sets.push({ time: set.week, data: [set]});
} else {
// If week is already being tracked, add data to week
trackedWeek.data.push(set);
}
};
for (let set of sets) {
// Find start
const start = set.data.reduce((min, { start }) => {
if (!min) return start;
return min > start ? start : min;
}, null);
// Find end
const end = set.data.reduce((max, { slut }) => {
if (!max) return slut;
return max < slut ? slut : max;
}, null);
// Accumulate resultat
const resultat = set.data.reduce((acc, { resultat }) => (acc += parseInt(resultat)), 0);
console.log("week: ", set.time);
console.log("start: ", start);
console.log("slut: ", end);
console.log("resultat: ", resultat);
}
Hope this helps. Take a look at Arrays and Objects and their methods. That is usually all you need to perform these kinds of manipulations.
i need to edit nested objects with unique key's! in couhdb document, but i can't do it.
my doc structure:
{
"_id":"20",
"_rev":"rev",
tasks": {
"20.t01": {
"name": "test",
"status": [],
"tasks": {
"20.t01t01": {
"status": [
],
"name": "name",
"tasks": {
"20.t01t01t01": {
"status": [],
"name": "name",
"tasks": {
"20.t01t01t01t01": {
"name": "name",
"status": [],
"tasks": {
}
}
}
}
}
}
}
}
}
}
I nedd to push some objects into status array's.
The update handler function:
"status": function(doc, req) {
var data = JSON.parse(req.body);
var value = data.value;
var path = data.path;
var message = 'set ' + path + ' status ' + value;
var pathar = path.split(".");
var level;
var body = doc;
var evalstr = "body.";
if (pathar[1].length > 2) {
level = (pathar[1].length) / 3;
for (var i = 1; i <= level - 1; i++) {
evalstr += "tasks[\"" + pathar[0] + "." + pathar[1].substring(0, i * 3) + "\"].";
}
evalstr += "tasks[\"" + pathar[0] + "." + pathar[1] + "\"].status.push(" + JSON.stringify(value) + ");";
} else {
level = 1;
evalstr += "tasks[\"" + pathar[0] + "." + pathar[1] + "\"].status.push(" + JSON.stringify(value) + ");";
}
eval([evalstr]);
doc = body;
//doc.tasks["20.t01"].tasks["20.t01t01"].status.push(value);
return [doc, JSON.stringify({
reg: evalstr,
doc: body
})];
}
how i write the design document update function for this structure in couchdb?
Tanks!
I'm getting too much recursion error at the following piece of code, when I'm running the application on Firefox. The code is expected to create a graphical tree structure in the browser. The method take a Json as an input, traverses through the keys and checks if the value corresponding to the key is "Leaf". If the value is "Leaf", it displays it on the browser and moves on to the next key, else it traverses recursively through the child nodes till the "Leaf" is reached. The node with all its children are displayed on the browser:
function createmasterJson(data) {
var json = '';
for (var index in data) {
var child = data[index];
if (child == 'Leaf') {
json = json + createLeafNode(index);
} else {
if (child.length) {
for (var i = 0; i < child.length; i++) {
json = json + createNonLeafNode(index, createmasterJson(child[i]));
}
} else {
json = json + createLeafNode(index);
}
}
}
return json;
}
function createLeafNode(index){
return '{ "attributes": { "id" :"' + index + '_' + Math.random() +'"}, "data": " '+ index +'" },';
}
function createNonLeafNode(index, child){
return '{ "attributes": { "id" :"' + index + '_' + Math.random() +'"}, "data": " '+ index +'" ,"state": "closed", "children" : ['+child.substring(0, child.length - 1)+']},';
}
I have the following array
array = [
{
"id": "67",
"sub": [
{
"id": "663",
},
{
"id": "435",
}
]
},
{
"id": "546",
"sub": [
{
"id": "23",
"sub": [
{
"id": "4",
}
]
},
{
"id": "71"
}
]
}
]
I am currently looping throught the array as follows
calling the array:
processArray(array);
the function loop
function processArray(arr)
{
for(var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id;
if(itemID != null)
{
$('.text').append(" ORDER : " + order + " Item ID : " + itemID + "<br />" );
}
if(typeof(value) == 'object') { //If it is an array,
processArray(arr[item]);
}
}
}
Currently i am getting the order of the item and the current ID no problem. What i need however (for my database schema) is for each item get the ID of its parent if there is one.
Do i need to pass the parent to each node? Or is there an easier way?
Thanks
Working demo
Include an optional parameter parentID in the function; by doing this, you can still use the processArray(array); syntax to process the original array.
function processArray(arr, parentID)
{
for(var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id;
if(itemID != null)
{
var output = " ORDER : " + order + " Item ID : " + itemID;
if( parentID ) { output += " PARENT : " + parentID; }
$('.text').append( output + "<br />");
}
// PROCESS SUB-ARRAY
if( typeof(value.sub) == 'object') { //If it is an array,
processArray( value.sub, itemID );
}
}
}
Use an auxiliary function that has id as part of its signature:
function processArray(arr) {
function _processArray(arr, id) {
for (var item in arr) {
var value = arr[item];
var order = item;
var itemID = value.id; // you need to change this because on the second call you pass in a string and not just an object
var parentId = id;
// Commenting the if statement that you had here actually shows the parent id's now.
$('.text').append(" ORDER : " + order + " Item ID : " + itemID + " Parent Id : " + parentId + "<br />");
if (typeof value === "object") { //use instanceof,
_processArray(arr[item], itemID);
}
}
}
_processArray(arr, 0);
}
I'm having trouble with a JavaScript array adding an extra undefined object after pushing some strings to the array.
$(function() {
var formTagArr = [];
$( "button", "#start-button" ).click(function() {
$.getJSON('http://127.0.0.1:8000/some_url/', function(data) {
formTagArr.push(buildForm(data));
console.log(formTagArr);
displayForm(formTagArr);
});
return false;
});
function buildForm(data) {
for (var i = 0; i < data.length; i++) {
var html = "";
var questionsTags = "<fieldset><p>" + data[i].question + "</p>";
var answersTags = "";
for (j = 0; j < data[i].answers.length; j++) {
answersTags += "<input type='radio' name='" + data[i].qid +
"' value='" + data[i].answers[j] + "' /" + ">" +
data[i].answers[j] + "\n";
}
html = questionsTags + answersTags + "</fieldset>";
formTagArr.push(html);
}
}
function displayForm(arr) {
if (arr.length === 0) {
return false;
}
var info = arr.pop();
$("#question-form").append(info[0]);
}
});
/some_url/ returns this JSON:
[{"qid": 4, "question": "How many legs does a spider have?", "answers": ["4", "6", "8", "10"]}, {"qid": 2, "question": "When did Nigeria become a republic?", "answers": ["1960", "1961", "1962", "1963"]}, {"qid": 1, "question": "When did Nigeria gain independence?", "answers": ["1960", "1961", "1962", "1963"]}, {"qid": 3, "question": "How many days are in a leap year?", "answers": ["360", "362", "365", "366"]}]
and console.log(formTagArr); in the code above returns:
["<fieldset><p>How many l...e='10' />10\n</fieldset>", "<fieldset><p>When did N...963' />1963\n</fieldset>", "<fieldset><p>When did N...963' />1963\n</fieldset>", "<fieldset><p>How many d...'366' />366\n</fieldset>", undefined]
Because of this, displayForm() fails since info is undefined. Of course I could just use a conditional to skip the undefined object but I want to know exactly how the undefined object got there in the first place.
What did i do wrong?
formTagArr.push(buildForm(data));
Your buildForm function doesn't return anything and the above code try to push the result of that function into the array. A function without a return statement would end up as undefined.
Seems like it should only be
buildForm(data)
As this function already pushed to the formTagArr array.
jsfiddle
You needed to remove the formTagArr.push call and also in the displayForm call change the line to this: $("#question-form").html(info);