Rebuild a JSON doc by Looping over the contents? - javascript

Am looking to .get an array of MongoDB docs, build var from the array using object.foo, and then reBuild an array of the all the foobar, once ranked..
Have another function that handles some variable calculations for ranking.
Am trying to reBuild the JSON array, using a for loop to iterate over the elements, but:
..the array starts with a comma for some odd reason
..looping over the newly built array seems to loop over the characters instead of the values
The console logs this: [01:10:40.833] ", {title: "Title1", quantity: "2", _id: "530c12c66e6b0de318000001"}, {title: "Title2", quantity: "4", _id: "530c12cc6e6b0de318000002"}, {title: "Title3", quantity: "8", _id: "530c12d16e6b0de318000003"}"
Then the console logs this: [01:10:40.833] undefined 213
MongoDB via .get:
function getAll(res) {
db.collection('demo').find().sort( { value: 1 } ).toArray(function (err, docs) {
console.log("Got the Docs: " + utils.inspect(docs));
// each doc looks like: { _id: ObjectID, title: 'string', quantity: int}
res.json({docs: docs});
});
}
Docs looks like this in the console:
[ { _id: 530c12c66e6b0de318000001,
title: 'Sample1',
quantity: 2 },
{ action: 'Sample2',
quantity: 4,
_id: 530c12cc6e6b0de318000002 },
{ _id: 530c12d16e6b0de318000003,
action: 'Sample3',
quantity: 8 } ]
Javascript Function to ReBuild the Array:
function reBuild(returnValue)
{
console.log(returnValue);
var docs = returnValue;
var returnedValue = [];
var doc;
for (var i=0, length=docs.length; i < length; i++){
doc = docs[i];
if (returnedValue == [])
{
returnedValue = returnedValue + '{' + 'title: "' + doc.title + '", quantity: "' + doc.quantity + '", _id: "' + doc._id + '"}';
}
else
{
returnedValue = returnedValue + ", " + '{' + 'title: "' + doc.title + '", quantity: "' + doc.quantity + '", _id: "' + doc._id + '"}';
}
}
console.log(returnedValue);
var newDocs = returnedValue;
var newDoc;
for (var i=0, length=newDocs.length; i < length; i++){
newDoc = newDocs[i];
console.log(newDoc.title);
}
}

See you can't simply assign String value to a array type variable. JavaScript allows you do so because it is a loosely typed(or dynamically typed). But it you case it is the cause for your problem.
In your code:
function reBuild(returnValue)
{
console.log(returnValue);
var docs = returnValue;
//==> Initializes to a array type i.e. equivalent to var returnedValue = new Array();
var returnedValue = [];
var doc;
for (var i=0, length=docs.length; i < length; i++){
doc = docs[i];
//==>Its better to use === if you want equality without type coersion. i.e. the values must be equal in type as well.
if (returnedValue == []){
//==>Here you are changing the type of `returnedValue` variable from array to String
//So this condition start failing from next loop onwards.
returnedValue = returnedValue + '{' + 'title: "' + doc.title + '", quantity: "' + doc.quantity + '", _id: "' + doc._id + '"}';
}
else{
returnedValue = returnedValue + ", " + '{' + 'title: "' + doc.title + '", quantity: "' + doc.quantity + '", _id: "' + doc._id + '"}';
}
}
console.log(returnedValue);
var newDocs = returnedValue;
var newDoc;
for (var i=0, length=newDocs.length; i < length; i++){
newDoc = newDocs[i];
console.log(newDoc.title);
}
}
You are changing the type of your variable returnedValue in a loop and also you are checking condition if (returnedValue == []). It automatically becomes false since it changes in first iteration from any array to String type. So the way you can look into is something array function such as arrayObject.push('YourValue')
Try the following code:
for (var i=0; i < docs.length; i++){
//This builds JSON object out of your string and pushes into your array `returnedValue`
returnedValue.push(JSON.prarse('{' + 'title: "' + docs[i].title + '", quantity: "' + docs[i].quantity + '", _id: "' + docs[i]._id + '"}'));
}
And the correct operator to typed check is to use ===. So basically the answer to your question is too broad But I did a attempt to point few of the points which takes you near to solution for your problem.
Happy coding :)

Related

Add items to JSON object

I'm picking up a JSON object using a promise:
var x = get();
x.done(function(data) {
for(var i in data) {
}
});
which is returning this data when i do console.log(data);
[{…}]
0:
customer: "9028"
data:
active: "1"
customer: "9028"
description: ""
id: "13717"
inherited: "0"
name: "Out of Hours"
priority: "1"
shared: "0"
sound: ""
__proto__: Object
voip_seq: "4"
__proto__: Object
length: 1
__proto__: Array(0)
so that is working fine, but within my for loop, I want to add 2 items to data
I tried adding this into my .done
var obj = { name: "Light" };
data.push(obj);
But that didn't add to data
My for loop looks like this:
for(var i in data) {
var m = '<option value="' + data[i].data.id + '"'
if(data[i].data.id == selected_val) {
m += ' selected="selected"';
}
m += '>' + data[i].data.name + '</option>';
$('#' + value_element_id).append(m);
}
If you want to add two more items to your select, you simply need to push new objects into your data array before your loop starts. The objects must contain the structure and properties ("name" and "id" within a "data" sub-property) matching the JSON coming from the Promise, so that your loop code can process them.
In the simplest case, it could be as straightforward as
x.done(function(data) {
data.push({ "data": { "name": "light", "id": 1234 } });
data.push({ "data": { "name": "dark", "id": 5678 } });
for(var i in data) {
var m = '<option value="' + data[i].data.id + '"'
if (data[i].data.id == selected_val) {
m += ' selected="selected"';
}
m += '>' + data[i].data.name + '</option>';
$('#' + value_element_id).append(m);
}
});
Demo: https://jsfiddle.net/a286b7fw/1/
In this case I think data is not an array so it hasn't .push() method. You can add property to object like this:
for(var i in data) {
var m = '<option value="' + data[i].data.id + '"'
if(data[i].data.id == selected_val) {
m += ' selected="selected"';
}
m += '>' + data[i].data.name + '</option>';
$('#' + value_element_id).append(m);
// here it will add obj to data
var obj = {name: "Light"};
data = {
...data,
obj
}
}

Dynamically set the "selected" attribute using Javascript

Here is my code:
$.ajax({
type: "POST",
url: "localhost/api.php",
data: {id:user_id},
cache: false,
success: function(data) {
var obj = $.parseJSON(data);
if (obj.msg == "1")
{
$.each(obj.userList, function(i,value) {
var jArray = <?php echo json_encode($groupData ); ?>;
list = [];
for (var i = 0; i < jArray.length; i++) {
list.push('<option id=' + jArray[i].Group_Id + ' value=' + jArray[i].Group_Name + '>' + jArray[i].Group_Name + '</option>');
}
var html ="<tr>"+
"<td>"+value['id']+"</td>"+
"<td>"+value['groupID']+"</td>"+
"<td><select name='Group[]''>"+list+ "</select></td>";
$('table#List tbody').append(html);
});
}
},
alert('Error');
});
I'm dynamically constructing the html based on the ajax response.
In the code snippet >
var jArray = <?php echo json_encode($groupData ); ?>;
list = [];
for (var i = 0; i < jArray.length; i++) {
list.push('<option id=' + jArray[i].Group_Id + ' value=' + jArray[i].Group_Name + '>' + jArray[i].Group_Name + '</option>');
}
$groupData is a PHP array. So I'm converting it into a Javascript array and using this jArray to generate the "option" and push the resulting list array. I'm appending this list array into the html and this much is working perfectly. Now there are 6 groups and one of them is already set for a particular user in the database. So currently none of the "option" has selected attribute. I'm having trouble in comparing jArray[i].Group_Id with value['groupID']. What I want to achieve is I want to compare jArray[i].Group_Id with value['groupID'] and if they are equal then set a selected attribute to that particular . How do I write an if statement for the comparison inside the "option" ?
Here's some example code showing this working:
const jArray = [{Group_Id: 1, Group_Name: 'One'}, {Group_Id: 2, Group_Name: 'Two'}];
const userList = [{id: 'user1', groupID: 2}, {id: 'user2', groupID: 2}, {id: 'user3', groupID: 1}];
$.each(userList, function(x,value) {
list = [];
for (var i = 0; i < jArray.length; i++) {
list.push('<option id=' + jArray[i].Group_Id + ' value=' + jArray[i].Group_Name + (jArray[i].Group_Id == value.groupID ? ' selected ' : '') + '>' + jArray[i].Group_Name + '</option>');
}
var html ="<tr>"+
"<td>"+value.id+"</td>"+
"<td>"+value.groupID+"</td>"+
"<td><select name='Group[]''>"+list+ "</select></td>";
$('table#List tbody').append(html);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="List">
<tbody></tbody>
</table>
The important piece missing from your code being:
(jArray[i].Group_Id == value.groupID ? ' selected ' : '')

How to print key and values from dictionaries enlisted in array, javascript

I am having difficulties printing data from dictionaries stored in an array using double for-loop with
var residents = [{name: "Pyrus", room: "32"},{name: "Ash Ketchum", room: "22"}];
function people() {
for (let i = 0; i < residents.length; i++) {
for (let j in residents[i]) {
document.write(j + ": " + residents[j] + "<br>");
}
}
};
people();
What I am retrieving is this:
name: undefined
room: undefined
name: undefined
room: undefined
I can print the key but it seems like it does not fetch value defined to the key!
What am I doing wrong?
A success criteria is to print in HTML.
You have chained two loops together so your function needs to access the parents index then the property that you wish to reference.
function people() {
for (let i = 0; i < residents.length; i++) {
for (let j in residents[i]) {
document.write(j + ": " + residents[i][j] + "<br>");
}
}
};
This is the simplest way I think(Use foreach()):
var residents = [{name: "Pyrus", room: "32"},{name: "Ash Ketchum", room: "22"}];
function people() {
residents.forEach(function(resident) {
document.write(resident.name + ": " + resident.room + "<br>");
});
}
people();
why not try like this with forEach()
var residents = [{
name: "Pyrus",
room: "32"
}, {
name: "Ash Ketchum",
room: "22"
}];
function people(residents) {
residents.forEach((element) => {
for (var key in element) {
if (element.hasOwnProperty(key)) {
console.log(key + ':' + element[key]);
}
}
});
};
people(residents);
You can avoid some of the for loops and make the code a little easier to read using forEach and Object.entries:
var residents = [{name: "Pyrus", room: "32"},{name: "Ash Ketchum", room: "22"}];
residents.forEach(res => {
Object.entries(res).forEach(([key, value]) => {
console.log(key + ": " + value ); //subing console.log so it prints here
//document.write(key + ": " + value + "<br>");
})
})
Using a regular for-loop it would go like the below code. Also, I strongly recommend you to check if all the properties (j) are own properties (with hasOwnProperty), otherwise this will look up in the prototype chain. This can be a problem if the objects are added to the array dynamically, otherwise you can bypass this check.
var residents = [{name:"Pyrus",room:"32"},{name: "Ash Ketchum",room:"22"}];
function people() {
for (let i = 0; i < residents.length; i++) {
for (let j in residents[i]) {
if (residents[i].hasOwnProperty(j)) { // <-- check if it is an own property!
document.write(j + ": " + residents[i][j] + "<br>");
//first access the object in residents[i], for example {name: "Pyrus",room: "32"}, then to its properties-values with residents[i][j]
}
}
}
};
people();
You need to access residents[i][j] since you are iterating residents in the first place.
so your code becomes :
document.write(j + ": " + residents[i][j] + "<br>");
See this working js fiddle
You could also write it like this :
function people(){
residents.forEach(r => {
for(let j in r){
document.write(j + ": " + r[j] + "<br>");
}
})
}
Hope this helps.

Alter matched item in for loop leaving the rest untouched

Not sure how to even title this question but i tried my best to condense it.
I have a key / value array that i need to loop through and print out as options to a select field. My issue is that i need to match an ID with a value in the array and give that option a selected attribute.
** Cannot use ES6 syntax **
My array:
groups =
[
{ name:"eng1",
value: "12"
},
{ name: "eng2",
value: "247"
},
{ name: "eng23",
value: "112"
},
];
My loop:
var targetGroupId = 247;
for (i = 0; i < groups.length; i++) {
if (groups[i].Value = targetGroupId) {
html += "<option value'" + groups[i].Value + "' selected='selected'>" + groups[i].Name + "</option>";
} else {
html += "<option value='" + groups[i].Value + "'>" + groups[i].Name + "</option>";
}
}
I need to print out all three items in the array as options. However the item matching targetGroupId needs to have the selected attribute.
Any guidance is much appreciated!
You have three issues
Comparing values with = rather than === .
You're using capitalized keys.
Comparing string with numbers.
var groups = [{name: "eng1",value: "12"},{name: "eng2",value: "247"},{name: "eng23",value: "112"},],
html = '',
targetGroupId = 247;
for (var i = 0; i < groups.length; i++) {
if (/*Convert to number ->*/+groups[i].value === targetGroupId) {
html += "<option value'" + groups[i].value + "' selected='selected'>" + groups[i].name + "</option>";
} else {
html += "<option value='" + groups[i].value + "'>" + groups[i].name + "</option>";
}
}
console.log(html);
You have the following issues with your code:
You are using Value property instead of value. Replace Value with value everywhere in your code.
Second, you need to correct this statement
if (groups[i].Value = targetGroupId) {
to this:
if (groups[i].value == targetGroupId) {
I've used == to auto-coerce the values for the comparison because targetGroupId is a number whereas value in the object is a string.
The keys name is case sensitive.So Value & Name need to be match the case
Also the value is string but the targetGroupId is integer. So need to convert the string to number or vice versa.
Beside groups[i].Value = targetGroupId is not right , you need to do the quality check instead of assigning the value
var groups = [{
name: "eng1",
value: "12"
},
{
name: "eng2",
value: "247"
},
{
name: "eng23",
value: "112"
},
];
var html = '';
var targetGroupId = 247;
for (i = 0; i < groups.length; i++) {
if (+groups[i].value === targetGroupId) {
html += "<option value'" + groups[i].value + "' selected='selected'>" + groups[i].name + "</option>";
} else {
html += "<option value='" + groups[i].value + "'>" + groups[i].name + "</option>";
}
}
document.getElementById('test').innerHTML = html
<select id='test'></select>

How to access all nested associative array elements?

Situation : I receive JSON array from jQuery <-> PHP Ajax request. Here's structure of unparsed JSON aray :
{"Focus":{"id":2,"brand":"Ford","name":"Focus"}}
And after using JSON.parse(json); the structure looks like :
Focus: Object
brand: "Ford"
id: 2
name: "Focus"
Problem : I want to access all array's '1st tier' elements and use them like an object, but none of the following ways works :
for (var entity in dataTable)
{
formattedText += entity['brand'] + " " + entity['name'] + "<br>";
OR
formattedText += entity.brand + " " + entity.name + "<br>";
OR
formattedText += dataTable[0]['brand'] + " " + dataTable[0]['name'] + "<br>";
}
Any solutions how to read values of all object in this array?
The for..in loop uses keys and does not return the elements themself: for (var key in dataTable)You would then access each element with dataTable[key]. The key is actually the name of the Element.
You where using it as you would use a for..of loop, but that is a new feature not supported in all Browsers yet.
Demo:
var dataTable = {"Focus":{"id":2,"brand":"Ford","name":"Focus"}}
var formattedText = ""
for (var key in dataTable)
{
formattedText += dataTable[key]['brand'] + " " + dataTable[key]['name'] + "<br>";
}
document.write(formattedText)
Object.keys will return array of all the keys of the object
You can loop(forEach/for-loop) through the keys to get the expected output.
Using forEach:
var dataTable = {
"Focus": {
"id": 2,
"brand": "Ford",
"name": "Focus"
}
}
var keys = Object.keys(dataTable);
var str = '';
keys.forEach(function(item) {
str += dataTable[item].brand + " " + dataTable[item].name;
});
alert(str);
Using for-loop:
var dataTable = {
"Focus": {
"id": 2,
"brand": "Ford",
"name": "Focus"
}
}
var keys = Object.keys(dataTable);
var str = '';
for (var i = 0, len = keys.length; i < len; i++) {
str += dataTable[keys[i]].brand + " " + dataTable[keys[i]].name;
}
alert(str);
The correct syntax to write this would be:
When you loop, you'll get the key name in the variable entity and then use that to get the value, also, you need to access the associative array inside the first key i.e. Focus
var dataTable = JSON.parse('{"Focus":{"id":2,"brand":"Ford","name":"Focus"}}');
var formattedText = '';
for (var entity in dataTable.Focus) {
formattedText += dataTable.Focus['brand'] + " " + dataTable.Focus['name'] + "<br>";
}
Sounds like you're using each function in a wrong way. in your each function change arguments to key and value like this:
$.each(dataTable, function (key, value) {
//access key and values here
});
In your case u should iterate again over key and values of your key values.

Categories