Defining variables for JS lp-solver using an array - javascript

I'm trying to create a linear programing code in JS using lp-solver library, but I can't get the results to be outputted. It's probably because of incorrect model, because the results output for each product and "total cost" shows as undefined, so I'm guessing that the model doesn't work at all. The problem is that I'm not just inputting the variables by myself, but I fetch the products from a database (that is working correctly and I can output, for example, the first product's name as data[0]['name'] and it works just fine) so they are written in an array. I made a for loop trying to input the data of products into variables of the model, but I guess that is not working correctly or the problem is somewhere else in the model. May you please help me?
Part of code:
<script>
// Make an AJAX request to the PHP script that fetches the products and user's desired
calories from the database
$.ajax({
url: 'fetchProductsFromDatabase.php',
success: function(response) {
var data = response;
var userCalories = data[0]['userCalories'];
// Set up the model
var model = {
optimize: "price",
opType: "min",
constraints: {
"calories": {
equal: userCalories
},
},
variables: {
},
};
// Set up the variables and the constraints in the model
for (var i = 0; i < data.length; i++) {
model.variables[data[i]['name']] = { "price": data[i]['price'], "calories": data[i]
['calories'] };
model.constraints[data[i]['name']] = { equal: 0 };
}
// Solve the linear program
var result = solver.Solve(model);
Proof of "data" output. Written as console.log(data[0]['name/price/calories']);
Results of the code.
for (var i = 0; i < data.length; i++) {
console.log(data[i]['name'] + ': ' + result[data[i]['name']]);
}
console.log('Total cost: ' + result.price);

Related

Code is not displaying JSON data

Hey guys I am trying to make a request to a JSON page, grabbing the data, then displaying it to my console but it is giving me "undefined". Why is that?
Here is the code and then the JSON page will be posted under it:
(function Apod() {
var api_key = 'NNKOjkoul8n1CH1NoUFo',
url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key,
data;
var apodRequest = new XMLHttpRequest();
apodRequest.onreadystatechange = function() {
if (apodRequest.readyState === 4 && apodRequest.status === 200) {
var response = apodRequest.responseText;
var parsedAPOD = JSON.parse(response);
data += parsedAPOD;
for (i = 0; i < parsedAPOD.length; i++) {
data += parsedAPOD[i];
console.log("Parsing lines: <br>" + parsedAPOD[i]);
}
}
apodRequest.open("GET", url, true);
apodRequest.send(null);
}
}());
JSON page parsing:
{
"date": "2016-11-05",
"explanation": "Shot in Ultra HD, this stunning video can take you on a tour of the International Space Station. A fisheye lens with sharp focus and extreme depth of field provides an immersive visual experience of life in the orbital outpost. In the 18 minute fly-through, your point of view will float serenely while you watch our fair planet go by 400 kilometers below the seven-windowed Cupola, and explore the interior of the station's habitable nodes and modules from an astronaut's perspective. The modular International Space Station is Earth's largest artificial satellite, about the size of a football field in overall length and width. Its total pressurized volume is approximately equal to that of a Boeing 747 aircraft.",
"media_type": "video",
"service_version": "v1",
"title": "ISS Fisheye Fly-Through",
"url": "https://www.youtube.com/embed/DhmdyQdu96M?rel=0"
}
You have a few errors in your code.
First off, the general structure of it should be like this
(function Apod() {
var api_key = 'NNKOjkoul8n1CH1NoUFo',
url = 'https://api.nasa.gov/planetary/apod' + "?api_key=" + api_key,
data;
var apodRequest = new XMLHttpRequest();
apodRequest.onreadystatechange = function() {
//Code here
};
apodRequest.open("GET", url, true);
apodRequest.send(null);
}());
Notice how I moved apodRequest.open("GET", url, true); and apodRequest.send(null); outside of the onreadystatechange handler.
Secondly, instead of
apodRequest.onreadystatechange = function() {
if (apodRequest.readyState === 4 && apodRequest.status === 200) {
//Code here
}
}
you can simply do
apodRequest.onload = function() {
//Code here
};
As it's the event that will fire when a response is returned. So you don't need the if check inside.
Finally, inside the onload handler, you have a few mistakes, such as:
data += parsedAPOD; this is wrong because data is an object undefined up to this point and parsedAPOD is an object. Doing += between two objects will not merge them. If you want to merge two objects there are other ways, e.g. Object.assign
for (i = 0; i < parsedAPOD.length; i++) { ... } is wrong because parsedAPOD is an object. Objects do not have a length property, so this is not the correct way to iterate over it. Use for ... in ... loop instead
data += parsedAPOD[i]; is, again, wrong, because this is not the way to merge objects.
parsedAPOD[i] is wrong because i is an integer, in this case, so parsedAPOD[i] is simply undefined.
Hope this analysis helps you correct your code.
first of all parsedAPOD is an object and parsedAPOD.length is not valid. You can use for in loop to iterate through an object as below.
for (var i in parsedAPOD) {
data += parsedAPOD[i];
console.log("Parsing lines: <br>" + parsedAPOD[i]);
}

Searching nested object with Elastic Search and Firebase

Following the Flashlight GitHub example by Firebase.com, I got it to work as instructed to deploy on Heroku - but the way my data is structured, I think there might be a better way?
My data structure looks like this:
(root)pages
-->Firebase Unique ID
---->chat
---->content
------>Firebase Unique ID
-------->title
-------->description
-------->filter = article
---------->tags
------------tag 1
------------tag 2
I only want Elastic Search to return results based on matching the tags or the filter = article, but I get everything from pages down (all the chat, all the content regardless if it matched the result, but not content from other pages, etc...)
The path in config.js for the flashlight code is simply:
exports.paths = [
{
path: "pages",
index: "firebase",
type: "pages"
},
{
path: "event_entry",
index: "firebase",
type: "events"
}
];
I'm still early enough in development that I can change the structure of the data; I thought about:
(root) content
-->Firebase Unique ID
---->title
---->description
---->filter = article
And then simply storing the Firebase Unique ID in the pages object somewhere?
As it stands right now, I'm parsing the result as so to check the tags and only show what is actually tagged with what I searched for and it's just... ugly...
function showResults(snap) {
if( snap.val() === null ) { return; } // wait until we get data
var dat = snap.val();
var out = '';
$.each(dat["hits"]["0"]["_source"]["content"], function(i, v) {
for(var k in v.tags)
{
if(v['tags'][k]['text'] == $scope.search)
{
out += v.title + ": " + i + "<br>";
console.log(i);
}
}
});
$("#results").text(out);
}

Loop Through JSON, Insert Key/Value Between Objects?

UPDATE - Thanks for all the great answers and incredibly fast response. I've learned a great deal from the suggested solutions. I ultimately chose the answer I did because the outcome was exactly as I asked, and I was able to get it working in my application with minimal effort - including the search function. This site is an invaluable resource for developers.
Probably a simple task, but I can't seem to get this working nor find anything on Google. I am a Javascript novice and complex JSON confuses the hell out of me. What I am trying to do is make a PhoneGap Application (Phone Directory) for our company. I'll try to explain my reasoning and illustrate my attempts below.
I have JSON data of all of our employees in the following format:
[
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
The mobile framework (Framework 7) that I am using offers a "Virtual List" solution which I need to take advantage of as our directory is fairly large. The virtual list requires you to know the exact height of each list item, however, you can use a function to set a dynamic height.
What I am trying to do is create "headers" for the alphabetical listing based on their last name. The JSON data would have to be restructured as such:
[
{
"title":"A"
},
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer"
},
{
"title":"B"
},
{
"id":"2",
"firstname":"Mark",
"lastname":"Banana",
"jobtitle":"Artist"
},
... and so on
]
I've been able to add key/value pairs to existing objects in the data using a for loop:
var letter, newLetter;
for(var i = 0; i < data.length; i++) {
newLetter = data[i].lastname.charAt(0);
if(letter != newLetter) {
letter = newLetter
data[i].title = letter;
}
}
This solution changes the JSON, thus outputting a title bar that is connected to the list item (the virtual list only accepts ONE <li></li> so the header bar is a div inside that bar):
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
},
{
"id":"1",
"firstname":"Mike",
"lastname":"Apricot",
"jobtitle":"Engineer",
"title":""
}
This solution worked until I tried implementing a search function to the listing. When I search, it works as expected but looks broken as the header titles ("A", "B", etc...) are connected to the list items that start the particular alphabetical section. For this reason, I need to be able to separate the titles from the existing elements and use them for the dynamic height / exclude from search results.
The question: How can I do a for loop that inserts [prepends] a NEW object (title:letter) at the start of a new letter grouping? If there is a better way, please enlighten me. As I mentioned, I am a JS novice and I'd love to become more efficient programming web applications.
var items = [
{ "lastname":"Apple" },
{ "lastname":"Banana" },
{ "lastname":"Box" },
{ "lastname":"Bump" },
{ "lastname":"Can" },
{ "lastname":"Switch" }
];
var lastC = null; //holds current title
var updated = []; //where the updated array will live
for( var i=0;i<items.length;i++) {
var val = items[i]; //get current item
var firstLetter = val.lastname.substr(0,1); //grab first letter
if (firstLetter!==lastC) { //if current title does not match first letter than add new title
updated.push({title:firstLetter}); //push title
lastC = firstLetter; //update heading
}
updated.push(val); //push current index
}
console.log(updated);
Well right now you have an array of objects - prefixing the title as its own object may be a bit confusing - a better structure may be:
[
{
title: "A",
contacts: [
{
"id":"1",
"firstname":"John",
"lastname":"Apple",
"jobtitle":"Engineer",
"title":"A"
}
]
Given your current structure, you could loop and push:
var nameIndexMap = {};
var newContactStructure = [];
for (var i = 0; i < data.length; i++) {
var letter = data[i].lastname.charAt(0);
if (nameIndexMap.hasOwnProperty(letter)) {
//push to existing
newContactStructure[nameIndexMap[letter]].contacts.push(data[i])
} else {
//Create new
nameIndexMap[letter] = newContactStructure.length;
newContactStructure.push({
title: letter,
contacts: [
data[i]
]
});
}
}
newContactStructure will now contain your sorted data.
Demo: http://jsfiddle.net/7s50k104/
Simple for loop with Array.prototype.splice will do the trick:
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
Demo. Check the demo below.
var data = [
{"lastname":"Apple"},
{"lastname":"Banana"},
{"lastname":"Bob"},
{"lastname":"Car"},
{"lastname":"Christ"},
{"lastname":"Dart"},
{"lastname":"Dog"}
];
for (var i = 0; i < data.length; i++) {
if (i == 0 || data[i-1].lastname[0] !== data[i].lastname[0]) {
data.splice(i, 0, {title: data[i].lastname[0]});
i++;
}
}
alert(JSON.stringify( data, null, 4 ));

Create JSON from jQuery each loop

All the questions I have dug through in the boards aren't really answering a question I have. So I will ask the experts here. First off, thank you very much for reading on. I really appreciate what Stackoverflow is all about, hopefully I can contribute now that I am a member.
I want to dynamically create a JSON object based off variables set from another JSON object from with a jQuery each loop. I think my syntax and probably my knowledge of this stuff is a little off.
I would like to end up with the following JSON structure:
{
desktop:{
title:300,
rev:200
}
}
Where "desktop" is a value from another JSON object not in this loop, I can call that no problem, in fact it is actually the name value I set on the other JSON object. I am looping through an array in the object called columns but want to set a separate object containing all the widths because the columns are adjustable and accessible via another frame that I will push it to, I want to retain those widths.
I was trying to do this from within the loop:
var colWidths = {};
$.each(columns, function(i) {
colWidths.desktop.title = columns[i].width;
});
I can alert columns[i].width successfully. The issue I have is creating and accessing this. Everything I seem to be doing seems right but this is not the case. Maybe its me or my setup? Could you please show me how to code this properly? OR I could create a Javascript Object if this is not possible. Thanks in advance!
Welcome to Stackoverflow. You did not write any error messages you got, so I assume the following.
// prepare the object correctly first
var colWidths = {
desktop: {
title: 0
}
};
// then ADDING each value with += instead of =
// (because in your code you will just have the last value)
$.each(columns, function(i) {
colWidths.desktop.title += columns[i].width;
});
EDIT
var grid = {
"name": "desktop",
"columns": [
{
"id": "icons",
"width": 50},
{
"id": "title",
"width": 200},
{
"id": "name",
"width": 300},
{
"id": "revision",
"width": 400}
]
};
var columns = grid.columns;
var gridName = grid.name;
var colWidths = {};
// CHANGE HERE
colWidths[gridName] = {};
$.each(columns, function(c) {
var col = columns[c];
var colname = col.id;
var colwidth = col.width;
// CHANGE HERE
var thisGrid = colWidths[gridName];
if(!thisGrid[colname]) thisGrid[colname] = 0;
thisGrid[colname] += colwidth;
});
//alert(colWidths.desktop.title);​
document.write(JSON.stringify(colWidths));
// RESULT:
// {"desktop":{"icons":50,"title":200,"name":300,"revision":400}}

Javascript how to parse JSON array

I'm using Sencha Touch (ExtJS) to get a JSON message from the server. The message I receive is this one :
{
"success": true,
"counters": [
{
"counter_name": "dsd",
"counter_type": "sds",
"counter_unit": "sds"
},
{
"counter_name": "gdg",
"counter_type": "dfd",
"counter_unit": "ds"
},
{
"counter_name": "sdsData",
"counter_type": "sds",
"counter_unit": " dd "
},
{
"counter_name": "Stoc final",
"counter_type": "number ",
"counter_unit": "litri "
},
{
"counter_name": "Consum GPL",
"counter_type": "number ",
"counter_unit": "litri "
},
{
"counter_name": "sdg",
"counter_type": "dfg",
"counter_unit": "gfgd"
},
{
"counter_name": "dfgd",
"counter_type": "fgf",
"counter_unit": "liggtggggri "
},
{
"counter_name": "fgd",
"counter_type": "dfg",
"counter_unit": "kwfgf "
},
{
"counter_name": "dfg",
"counter_type": "dfg",
"counter_unit": "dg"
},
{
"counter_name": "gd",
"counter_type": "dfg",
"counter_unit": "dfg"
}
]
}
My problem is that I can't parse this JSON object so that i can use each of the counter objects.
I'm trying to acomplish that like this :
var jsonData = Ext.util.JSON.decode(myMessage);
for (var counter in jsonData.counters) {
console.log(counter.counter_name);
}
What am i doing wrong ?
Thank you!
Javascript has a built in JSON parse for strings, which I think is what you have:
var myObject = JSON.parse("my json string");
to use this with your example would be:
var jsonData = JSON.parse(myMessage);
for (var i = 0; i < jsonData.counters.length; i++) {
var counter = jsonData.counters[i];
console.log(counter.counter_name);
}
Here is a working example
EDIT: There is a mistake in your use of for loop (I missed this on my first read, credit to #Evert for the spot). using a for-in loop will set the var to be the property name of the current loop, not the actual data. See my updated loop above for correct usage
IMPORTANT: the JSON.parse method wont work in old old browsers - so if you plan to make your website available through some sort of time bending internet connection, this could be a problem! If you really are interested though, here is a support chart (which ticks all my boxes).
In a for-in-loop the running variable holds the property name, not the property value.
for (var counter in jsonData.counters) {
console.log(jsonData.counters[counter].counter_name);
}
But as counters is an Array, you have to use a normal for-loop:
for (var i=0; i<jsonData.counters.length; i++) {
var counter = jsonData.counters[i];
console.log(counter.counter_name);
}
This is my answer:
<!DOCTYPE html>
<html>
<body>
<h2>Create Object from JSON String</h2>
<p>
First Name: <span id="fname"></span><br>
Last Name: <span id="lname"></span><br>
</p>
<script>
var txt =
'{"employees":[' +
'{"firstName":"John","lastName":"Doe" },' +
'{"firstName":"Anna","lastName":"Smith" },' +
'{"firstName":"Peter","lastName":"Jones" }]}';
//var jsonData = eval ("(" + txt + ")");
var jsonData = JSON.parse(txt);
for (var i = 0; i < jsonData.employees.length; i++) {
var counter = jsonData.employees[i];
//console.log(counter.counter_name);
alert(counter.firstName);
}
</script>
</body>
</html>
Just as a heads up...
var data = JSON.parse(responseBody);
has been deprecated.
Postman Learning Center now suggests
var jsonData = pm.response.json();
Something more to the point for me..
var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);
document.write(contact.surname + ", " + contact.firstname);
document.write(contact.phone[1]);
// Output:
// Aaberg, Jesper
// 555-0100
Reference:
https://learn.microsoft.com/en-us/scripting/javascript/reference/json-parse-function-javascript
"Sencha way" for interacting with server data is setting up an Ext.data.Store proxied by a Ext.data.proxy.Proxy (in this case Ext.data.proxy.Ajax) furnished with a Ext.data.reader.Json (for JSON-encoded data, there are other readers available as well). For writing data back to the server there's a Ext.data.writer.Writers of several kinds.
Here's an example of a setup like that:
var store = Ext.create('Ext.data.Store', {
fields: [
'counter_name',
'counter_type',
'counter_unit'
],
proxy: {
type: 'ajax',
url: 'data1.json',
reader: {
type: 'json',
idProperty: 'counter_name',
rootProperty: 'counters'
}
}
});
data1.json in this example (also available in this fiddle) contains your data verbatim. idProperty: 'counter_name' is probably optional in this case but usually points at primary key attribute. rootProperty: 'counters' specifies which property contains array of data items.
With a store setup this way you can re-read data from the server by calling store.load(). You can also wire the store to any Sencha Touch appropriate UI components like grids, lists or forms.
This works like charm!
So I edited the code as per my requirement. And here are the changes:
It will save the id number from the response into the environment variable.
var jsonData = JSON.parse(responseBody);
for (var i = 0; i < jsonData.data.length; i++)
{
var counter = jsonData.data[i];
postman.setEnvironmentVariable("schID", counter.id);
}
The answer with the higher vote has a mistake. when I used it I find out it in line 3 :
var counter = jsonData.counters[i];
I changed it to :
var counter = jsonData[i].counters;
and it worked for me.
There is a difference to the other answers in line 3:
var jsonData = JSON.parse(myMessage);
for (var i = 0; i < jsonData.counters.length; i++) {
var counter = jsonData[i].counters;
console.log(counter.counter_name);
}
You should use a datastore and proxy in ExtJs. There are plenty of examples of this, and the JSON reader automatically parses the JSON message into the model you specified.
There is no need to use basic Javascript when using ExtJs, everything is different, you should use the ExtJs ways to get everything right. Read there documentation carefully, it's good.
By the way, these examples also hold for Sencha Touch (especially v2), which is based on the same core functions as ExtJs.
Not sure if my data matched exactly but I had an array of arrays of JSON objects, that got exported from jQuery FormBuilder when using pages.
Hopefully my answer can help anyone who stumbles onto this question looking for an answer to a problem similar to what I had.
The data looked somewhat like this:
var allData =
[
[
{
"type":"text",
"label":"Text Field"
},
{
"type":"text",
"label":"Text Field"
}
],
[
{
"type":"text",
"label":"Text Field"
},
{
"type":"text",
"label":"Text Field"
}
]
]
What I did to parse this was to simply do the following:
JSON.parse("["+allData.toString()+"]")

Categories

Resources