Javascript: Printing array of a constructor class - javascript

Posting only the parts needed.
// This program simulates purchases of musical albums through a loop.
// The user initially has 1000 dollars. As the program loops through the albums
// the user purchases random quantities. The program adds the subtotals and
// subtracts from the initial total to find out what the user has left.
// Variables for random quantity.
var min = 1,
max = 25;
// Constructor for Album class
function Album(title, artist, price, release){
this.title = title;
this.artist = artist;
this.price = price;
this.release = release;
this.quantity = (Math.floor(Math.random() * max) + min);
this.subtotal = this.quantity * this.price;
};
Album.prototype.purchase = function(){
this.quantity--;
if (this.quantity > 0){
return 1;
}
else{
return -1;
}
};
// Constructor for Cart class
function Cart(val){
this.items = [];
};
Cart.prototype.add = function(val){
this.items.push(val);
};
Cart.prototype.remove = function(val){
this.items.splice(albums.indexOf(val), 1);
};
// Object that inherit from the Album class.
var nothingSame = new Album('Nothing Was the Same', "Drake", 15.99, "09/24/2013");
nothingSame.tracklisting = ["Started from the Bottom", "All Me", "Pound Cake", "The Language"];
var lifeOfPablo = new Album("The Life of Pablo", "Kanye West", 15.98, "02/14/2016");
lifeOfPablo.tracklisting = ["Ultralight Beam", "Famous", "Feedback", "Low Lights"];
var babel = new Album("Babel", "Mumford & Sons", 13.83, "09/21/2012");
babel.tracklisting = ["I Will Wait", "Lover of the Light", "Whispers in the Dark", "Babel"];
var ghostStories = new Album("Ghost Stories", "Coldplay", 12.61, "05/16/2014");
ghostStories.tracklisting = ["Magic", "Midnight", "A Sky Full of Stars", "True Love"];
var trueAlbum = new Album("True", "Avicii", 15.99, "09/13/2013");
trueAlbum.tracklisting = ["Wake Me Up", "You Make Me", "Hey Brother", "Lay Me Down"];
// Array of the albums for the objects within them.
var albums = [nothingSame, lifeOfPablo, babel, ghostStories, trueAlbum];
//Variables the initial amount of money
var INITIAL_MONEY = 1000.00;
var n = 1000.00;
// Instance of cart.
var cart = new Cart();
// Loop that simulates the purchase.
var i = 0;
while(INITIAL_MONEY > 0 && i < albums.length){
if (INITIAL_MONEY >= albums[i].subtotal){
albums[i].purchase();
INITIAL_MONEY = INITIAL_MONEY - albums[i].subtotal;
cart.add(albums[i]);
}
i++;
}
// Variable for the total amount spent.
var total = n - INITIAL_MONEY;
// Console logs to output all the data to the user.
console.log("You walk into a store with $1000 and purchase several albums.")
console.log(cart);
console.log("Total: " + total.toFixed(2));
console.log("Money Remaining: " + INITIAL_MONEY.toFixed(2));
Output Example:
You walk into a store with $1000 and purchase several albums.
Cart {
items:
[ Album {
title: 'Nothing Was the Same',
artist: 'Drake',
price: 15.99,
release: '09/24/2013',
quantity: 22,
subtotal: 367.77,
tracklisting: [Object] },
Album {
title: 'The Life of Pablo',
artist: 'Kanye West',
price: 15.98,
release: '02/14/2016',
quantity: 1,
subtotal: 31.96,
tracklisting: [Object] },
Album {
title: 'Babel',
artist: 'Mumford & Sons',
price: 13.83,
release: '09/21/2012',
quantity: 1,
subtotal: 27.66,
tracklisting: [Object] },
Album {
title: 'Ghost Stories',
artist: 'Coldplay',
price: 12.61,
release: '05/16/2014',
quantity: 4,
subtotal: 63.05,
tracklisting: [Object] },
Album {
title: 'True',
artist: 'Avicii',
price: 15.99,
release: '09/13/2013',
quantity: 18,
subtotal: 303.81,
tracklisting: [Object] } ] }
Total: 794.25
Money Remaining: 205.75
I can't figure out how to get the track listing to show. Closest I got to it, it only showed the last track in the array for all of them. I can't seem to get each of the albums to display the listed tracks in the output.

If you want to output this for debugging or toString purposes, you can try JSON.stringify(albums, null, 2).
If you want it displayed in the console, using console.log, try console.log(JSON.stringify(albums, null, 2))
Edit:
Applied to your Cart implementation, use console.log(JSON.stringify(cart, null, 2)) in place of console.log(cart).
Sample output
{
"items": [
{
"title": "Nothing Was the Same",
"artist": "Drake",
"price": 15.99,
"release": "09/24/2013",
"quantity": 18,
"subtotal": 303.81,
"tracklisting": [
"Started from the Bottom",
"All Me",
"Pound Cake",
"The Language"
]
},
{
"title": "The Life of Pablo",
"artist": "Kanye West",
"price": 15.98,
"release": "02/14/2016",
"quantity": 15,
"subtotal": 255.68,
"tracklisting": [
"Ultralight Beam",
"Famous",
"Feedback",
"Low Lights"
]
},
{
"title": "Babel",
"artist": "Mumford & Sons",
"price": 13.83,
"release": "09/21/2012",
"quantity": 16,
"subtotal": 235.11,
"tracklisting": [
"I Will Wait",
"Lover of the Light",
"Whispers in the Dark",
"Babel"
]
},
{
"title": "True",
"artist": "Avicii",
"price": 15.99,
"release": "09/13/2013",
"quantity": 10,
"subtotal": 175.89000000000001,
"tracklisting": [
"Wake Me Up",
"You Make Me",
"Hey Brother",
"Lay Me Down"
]
}
]
}

If you just want to dump the contents of the created object to console, then it's not much of a js problem, but more of dealing with quirks of the console you're using... E.g. some consoles collapse nested objects.
In most cases you can dump the objects to string and output that, it's a good debugging aproach (which additionally gives you a view of an object from the time of the console call execution, not a reference to an object that might change later):
JSON.stringify(albums);
so in typical console call:
console.log(JSON.stringify(albums));

Looping through the album instances tracklisting property manually, you can get the individual items:
// Loop over the albums array
for(var i = 0; i < albums.length; ++i){
// Loop through the tracklisting array elements for the current album
for(var x = 0; x < albums[i].tracklisting.length; ++x){
console.log(albums[i].tracklisting[x]);
}
}
But, how about:
var albumString = JSON.stringify(albums);
console.log(albumString);
To simply turn the entire object structure into a string?

Related

Uncaught TypeError: Cannot read properties of undefined while looping objects

So , I have 2 objects that are made of products , the main and the secondary , i have made a loop that searches in the main , and if it does not find the product , it deletes is from the secondary, Even though , with 10 products it worked, now that i have 1470 products the loop stops on the 4th repeat and says << Uncaught TypeError: Cannot read properties of undefined (reading 'name') >> , Here is the code
function deleter(){
let main = main_products;
let secondary= secondary_products;
let i;
let counter = 0;
console.log(main);
console.log(secondary); // just to be sure the data is ok
for (i=0;i<1550;i++){
counter = 0;
while (secondary[i].name !== main[counter].name){
counter ++;
if (counter === 1550){
break ;
} // i did this with break i dont know why i did though
}
if (secondary[i].name === main[counter].name){
console.log("found -> " + secondary[i].name);
}
else {
console.log("did not find product -> "+ secondary[i].name +" on the main database . . . ");console.log("initializing product deletion . . .");
console.log(secondary[i].id);
deletedata();
document.getElementById("delete").innerHTML = "Done ✔️";
}
}
}
when i loop 10 products it works fine every time . Do i need to do something else now that the products are significantly more?
Edit
So the objects are made like this and i take the from woocommerce
[
{
"id": 67537,
"name": "test 10",
"slug": "",
"type": "simple",
"status": "draft",
"featured": false,
"catalog_visibility": "visible",
"description": "allagi\n",
"short_description": "",
"sku": "1230975071-1-1-1-1-1-1-1-1-1",
"price": "123122",
"regular_price": "123123",
"sale_price": "123122"
}
{
"id": 67536,
"name": "test 9",
"slug": "",
"type": "simple",
"status": "draft",
"featured": false,
"catalog_visibility": "visible",
"description": "allagi\n",
"short_description": "",
"sku": "1230975071-2",
"price": "123122",
"regular_price": "123123",
"sale_price": "123122"}]
Here is a picture
both objects are from woo
The problem is - you are running out of the bounds of you product array. It's caused by:
You have 1470 products, but iterating over 1550 for (i = 0; i < 1550; i++). Can be fixed with for (i = 0; i < secondary.length; i++)
No additional checks do we have next element or not in while loop
So I suppose fixed and optimized version of code may look like this:
const main_products = [{id: 1, name: 'blabla1'}, {id: 2, name: 'blabla2'}, {id: 3, name: 'blabla3'}];
const secondary_products = [{id: 2, name: 'blabla2'}, {id: 4, name: 'blabla4'}, {id: 5, name: 'blabla5'}];
deleter();
function deleter() {
let main = main_products;
let secondary = secondary_products;
for (let i = 0; i < secondary.length; i++) {
const productWeFound = main.find((product) => secondary[i].name === product.name);
if (productWeFound) {
console.log("found -> " + secondary[i].name);
} else {
console.log("did not find product -> " + secondary[i].name + " on the main database . . . ");
console.log("initializing product deletion . . .");
console.log(secondary[i].id);
// deletedata();
// document.getElementById("delete").innerHTML = "Done ✔️";
}
}
}

Using Assertion to check array in JSON in API is giving error

I am trying test do an API test using PostMan, I am trying to check if a specific book name exists with the data that is being returned back from the GET call. The data that is coming back is an array.
This is the JSON:
{
"docs": [
{
"_id": "5cf5805fb53e011a64671582",
"name": "The Fellowship Of The Ring"
},
{
"_id": "5cf58077b53e011a64671583",
"name": "The Two Towers"
},
{
"_id": "5cf58080b53e011a64671584",
"name": "The Return Of The King"
}
],
"total": 3,
"limit": 1000,
"offset": 0,
"page": 1,
"pages": 1
}
This is the test that I have written:
let jsonData = pm.response.json()
console.log(jsonData);
pm.test('Check Book Name, () =>{
_.each(jsonData.docs, (docs)=>{
pm.expect(docs.name).to.eql("The Fellowship Of The Ring");
})
});
I am getting following error:
Your test name | AssertionError: expected 'The Two Towers' to deeply
equal 'The Fellowship Of The Ring'
I don't understand why its checking The Two Towers instead of The Fellowship which clearly exists within the array
You're expecting each returned book to have the name The Fellowship Of The Ring.
You could use a loop to check for each book:
let jsonData = pm.response.json();
const expectedBooks = ["The Fellowship Of The Ring", "The Two Towers", "The Return Of The King"]
var numberOfBooks = expectedBooks.length;
for (var i = 0; i < numberOfBooks; i++){
pm.test('Check Book Name ' + i, function () {
pm.expect(jsonData.docs[i].name).to.eql(expectedBooks[i]);
});
}

MongoDB - finding common value count between a set of documents

I have the documents in the with the two fields and I want to find common value count between a same set (category) of rows: e.g.
Current data look something like this (assume in Json format):
I need an output like this:
Will be grateful for any guidance/pointers. Thanks
First, get your data in the form of an array of objects. Then, we can use the following algorithm to get what you need:
Get the unique categories ["Music", "Film", "History", "Science"]
Get the combinations of those categories [["Music", "Film"], ["Music", "History"], ["Music", "Science"], ["Film", "History"], ...]
Create a mapping of category name to the books that are contained in that category. We can use a Set to ensure that the values are unique. The map will have the structure like {"Music": Set("A", "B"), "Film": Set("A", "B", "C"), "History": Set("C", "B"), "Science": Set("C")}
Use the objects and arrays that you just created to find the duplicates between the combinations.
When all is said and done, you'll have an array that has the following structure: [ [cat1, cat2, [bookInCommon1, bookInCommon2]], [cat1, cat3, [bookInCommon1, bookInCommon2]], ...]
Run the code below to see it in action. mongoData holds the data that is fetched from Mongo.
const mongoData = [{
category: "Music",
book: "A"
}, {
category: "Music",
book: "B"
},{
category: "Music",
book: "A"
},{
category: "Film",
book: "A"
},{
category: "Film",
book: "A"
},{
category: "Film",
book: "B"
},{
category: "Film",
book: "C"
},{
category: "Film",
book: "C"
},{
category: "Film",
book: "A"
},{
category: "History",
book: "C"
},{
category: "History",
book: "C"
},{
category: "History",
book: "B"
},{
category: "History",
book: "B"
},{
category: "Science",
book: "C"
},{
category: "Science",
book: "C"
},{
category: "Science",
book: "C"
}];
// Step 1: Get the categories
const categories = Array.from(new Set(mongoData.map(x => x.category)));
// Step 2: Get combinations of those categories
const combos = [];
for(let i = 0; i < categories.length - 1; i++) {
let outerCat = categories[i];
for(let j = i + 1; j < categories.length; j++) {
let innerCat = categories[j];
combos.push([
outerCat,
innerCat
]);
}
}
// Step 3: Map the categories to the books that they contain
const catBooks = mongoData.reduce((map, entry) => {
map[entry.category] = map[entry.category] || new Set();
map[entry.category] = map[entry.category].add(entry.book);
return map;
}, {});
// Step 4: Get the duplicate books for each combo
combos.forEach((combo, index) => {
const cat1 = combo[0];
const cat2 = combo[1];
const cat1BooksArr = Array.from(catBooks[cat1]);
const cat2BooksSet = catBooks[cat2];
const dupes = cat1BooksArr.filter(book => {
return cat2BooksSet.has(book);
});
combos[index].push(dupes); // push into combos array
});
// Done! Your combos array contains arrays that look like this: [cat1, cat2, [dupes]]
combos.forEach(combo => {
console.log("Combo: " + combo[0] + ", " + combo[1]);
console.log("\tNumber of dupes: " + combo[2].length);
});

How would I loop through JSON and then sort a response by the key?

For instance I would like to loop through the JSON below, and then push only a home_team_conference if it has the string of Southeastern. I want to be able to sort by home_team_conference so that I can use each array on a separate page of my website. Right now I'm looping through the whole JSON document but it's returning all of them and I'd like to prevent that. I've searched this website and some others but I can't seem to find a solution. Any ideas?
{
id: "771",
api_id: "08183e9c-8abe-43a0-871e-b07a53a399f0",
status: "scheduled",
scheduled: "2017-11-22 12:00:00",
conference_game: false,
game_time_date: "2017-11-22",
game_time_hour: "12:00pm",
home_team: "Volunteers",
away_team: "Boilermakers",
venue: "Imperial Arena",
broadcast_network: "ESPN2",
broadcast_internet: "WatchESPN",
home_team_conference: "Southeastern",
away_team_conference: "Big Ten",
home_team_division: "NCAA Division I",
away_team_division: "NCAA Division I",
total_points_bet: 0
},
{
id: "772",
api_id: "342d431c-bcf0-4214-a868-40ebaae75feb",
status: "scheduled",
scheduled: "2017-11-22 13:00:00",
conference_game: false,
game_time_date: "2017-11-22",
game_time_hour: "1:00pm",
home_team: "Pioneers",
away_team: "Mariners",
venue: "William H. Pitt Center",
broadcast_network: "",
broadcast_internet: "",
home_team_conference: "Northeast",
away_team_conference: "New England Collegiate Conference",
home_team_division: "NCAA Division I",
away_team_division: "NCAA Division III",
total_points_bet: 0
},
Right now I'm doing this to loop through:
var test = [];
// This gets the game JSON and returns it so you can use it below.
function getGames(){
return $.getJSON('https://--------------.--------.com/dbdata/gameday/division');
}
getGames().done(function(results){
$.each(results, function (i, gameData){
$.each(gameData, function(key, game){
test.push(game);
var gameId = game.id;
var homeTeam = game.home_team;
var awayTeam = game.away_team;
var pointTotal = game.total_points_bet;
var gameTime = game.game_time_hour;
var gameDate = game.game_time_date;
var network = game.broadcast_network;
From what I understand, is you want to get a list of items from an array where home_team_conference = "Southeastern"
This will get you a list of teams where home_team_conference = "Southeastern"
let southeastern = teamArray.filter((team) => team.home_team_conference == "Southeastern")
console.log(southeastern)
I am not sure what you want for a sort feature because all items in home_team_conference will be the same same in that list. If you sort the whole list, you can do something like this:
// Change "home_team_conference" to something else to sort by that
teamArray.sort((a,b) => {
if (a.home_team_conference < b.home_team_conference) { return -1; }
if (a.home_team_conference > b.home_team_conference) { return 1; }
// names must be equal
return 0;
})
console.log(teamArray)
If you need a case insensitive search, convert both comparisons to lowercase with .toLowerCase()

Node js queue return elements from an array

I'm trying to implement a queue in node js.I have an array with elements and i want at every 1 sec to insert a new one.I want to return every time only two elements from queue(at every 5 seconds).I want the queue to continue returning values from where remains.An example.I have an array [1,2,3,4].At every 2 sec i insert a new elemt in array.I return 2 elements from array at every 5 sec.Does anyone know how to make this work? Here is my code:
var queue = require('queue');
var posts=["aaa","bbbb","ccc",'ddd'];
var n=posts.length;
function populateQueue(q) {
for (var i = 0; i < posts.length; i++) {
(function(index) {
q.push(function(done) {
console.log('done', posts[index]);
setTimeout(done, 5000);
posts.splice(0,2);
});
})(i);
}
}
function insert() {
posts.push({"name":haiku()});
cxc();
}
function cxc() {
populateQueue(q2);
}
setInterval(insert,2000);
var q2 = queue({concurrency: 2});
populateQueue(q2);
q2.start();
function haiku(){
var adjs = ["autumn", "hidden", "bitter", "misty", "silent", "empty", "dry",
"dark", "summer", "icy", "delicate", "quiet", "white", "cool", "spring",
"winter", "patient", "twilight", "dawn", "crimson", "wispy", "weathered",
"blue", "billowing", "broken", "cold", "damp", "falling", "frosty", "green",
"long", "late", "lingering", "bold", "little", "morning", "muddy", "old",
"red", "rough", "still", "small", "sparkling", "throbbing", "shy",
"wandering", "withered", "wild", "black", "young", "holy", "solitary",
"fragrant", "aged", "snowy", "proud", "floral", "restless", "divine",
"polished", "ancient", "purple", "lively", "nameless"]
, nouns = ["waterfall", "river", "breeze", "moon", "rain", "wind", "sea",
"morning", "snow", "lake", "sunset", "pine", "shadow", "leaf", "dawn",
"glitter", "forest", "hill", "cloud", "meadow", "sun", "glade", "bird",
"brook", "butterfly", "bush", "dew", "dust", "field", "fire", "flower",
"firefly", "feather", "grass", "haze", "mountain", "night", "pond",
"darkness", "snowflake", "silence", "sound", "sky", "shape", "surf",
"thunder", "violet", "water", "wildflower", "wave", "water", "resonance",
"sun", "wood", "dream", "cherry", "tree", "fog", "frost", "voice", "paper",
"frog", "smoke", "star"];
return adjs[Math.floor(Math.random()*(adjs.length-1))]+"_"+nouns[Math.floor(Math.random()*(nouns.length-1))];
}
I have a quick answer to this. Specifically involving your question, but not your code. You have to tell me what your code does, otherwise I can't help you with it. But to do with your question, I have this:
First, setup your initial queue and index.
let queue = [1, 2, 3, 4, 5],
index = 0;
Now you have to declare two functions, (1) The one that enqueues values in your array. In my case, I enqueue a random number
enqueue = () => {
queue.push(Math.floor(Math.random()*10));
console.log(queue);
}
The other one gets two values at the current index, and increments the index by 2, once the storing is done. The values are then, returned.
get_two_elements = () => {
let pointed_slice = queue.slice(index, index + 2);
index += 2;
console.log(pointed_slice);
return pointed_slice;
};
Finally, to make the contraption work, you have to put timeouts on them like this
setInterval(enqueue, 2000);
setInterval(get_two_elements, 5000);
Set interval is non-blocking, thus both will happen at almost the sametime with a difference ranging between nanoseconds and milliseconds. This will successfully do what your question sounds like to me.
For reference, I placed a gist on the whole code for you here:
https://gist.github.com/jekku/012eed5ea9c356f8fa29

Categories