I want to make a comparison of an object literal which looks like so...
receipt.tab = {Cafe Latte: 4.75, Cappucino: 3.85}
The items are added when I call the method addItemAndPrice(item) as found bellow...
var Receipt = function(){
this.tab = {};
};
Receipt.prototype.addItemAndPrice = function(item){
if (comparisonHere???){
this.tab[item] = this.tab[item] + this.tab[item] = menu.prices[item];
} else {
this.tab[item] = menu.prices[item];
}
};
I want to call the method and if there is already a Cafe Latte found within the tab then I want to add the value of that item to the corresponding item value.
and create this...
receipt.tab = {Cafe Latte: 9.50, Cappucino: 3.85}
FYI menu looks like this...
var menu = {
"shopName": "The Coffee Connection",
"address": "123 Lakeside Way",
"phone": "16503600708",
"prices":
{
"Cafe Latte": 4.75,
"Flat White": 4.75,
"Cappucino": 3.85,
"Single Espresso": 2.05,
"Double Espresso": 3.75,
"Americano": 3.75,
"Cortado": 4.55,
"Tea": 3.65,
"Choc Mudcake": 6.40,
"Choc Mousse": 8.20,
"Affogato": 14.80,
"Tiramisu": 11.40,
"Blueberry Muffin": 4.05,
"Chocolate Chip Muffin": 4.05,
"Muffin Of The Day": 4.55
}
}
You can use the hasOwnProperty method to check if a property exists. If it does, you would just change the value:
Receipt.prototype.addItemAndPrice = function(item){
if (this.tab.hasOwnProperty(item)){
this.tab[item] += menu.prices[item];
} else {
this.tab[item] = menu.prices[item];
}
};
You can simplify this if you know that a valid value can never be false, or if that value can be considered zero. Then you can just replace any falsy value with zero and assign the sum:
Receipt.prototype.addItemAndPrice = function(item){
this.tab[item] = (this.tab[item] || 0) + menu.prices[item];
};
if (receipt.tab.hasOwnProperty(item)) {...} is best, because it catches cases where receipt.tab[item] is defined but falsy (like {'Caffe Latte': 0}), but in your case, if (receipt.tab[item]) {...} probably works because all falsy values should resolve to 0 anyway.
Related
Could someone help me with this code, I'm trying to write a function that takes in a name from an object and returns a name tag :
"Hi! I'm [name], and I'm from [country]."
I've tried this code
const GUEST_LIST = {
Randy: "Germany",
Karla: "France",
Wendy: "Japan",
Norman: "England",
Sam: "Argentina"
}
function greeting(name) {
var x = Object.keys(GUEST_LIST);
const array = Object.keys(GUEST_LIST)
.map(function(key) {
return GUEST_LIST[key];
});
var txt ="";
for (let i in x)
{
if (name === x[i])
{
txt = "Hi I'm "+x[i] +", and I'm from " +array[i];
}
else
{
txt = "Hi! I'm a guest";
}
}
return txt;
}
console.log(greeting("Randy"))
but it always returns "Hi! I'm a guest" except when I type Sam,
Your issue is that your for loop will continue to loop over the other names in your x array even after you have found a name from your array that matches the name you passed into your function. That means on further iterations of your for loop, your else block of your code will run and overwrite the value of txt previously set. That's why "Sam" works, as that's the last name in your x array, and so txt doesn't get overwritten by further iterations of your for loop.
Another thing to note about your code, a for...in loop shouldn't be used to iterate over an array. It can lead to unwanted values being accessed, as it doesn't just loop over the indices of your array, but rather other properties.
With that being said, you're over-engineering your code. Currently, your object stores key-value pairs. The key is the name and the value is the country. For each key in your object, you can access it using bracket-notation:
console.log(GUEST_LIST["Randy"]); // Germany
With that idea in mind, your name variable can be used as the key for your object, which can then be used to obtain the country. If the GUEST_LIST object doesn't contain your key (ie: the value returned by trying to access the key from your object is falsy), then you can return your default "Hi! I'm a guest" text:
const GUEST_LIST = {
Randy: "Germany",
Karla: "France",
Wendy: "Japan",
Norman: "England",
Sam: "Argentina"
};
function greeting(name) {
const country = GUEST_LIST[name];
if(country)
return "Hi I'm "+name +", and I'm from " +country;
else
return "Hi! I'm a guest";
}
console.log(greeting("Randy"));
Since there are no specifications, why there should a for loop, why not make it a bit more simple?
const GUEST_LIST = {
Randy: 'Germany',
Karla: 'France',
Wendy: 'Japan',
Norman: 'England',
Sam: 'Argentina'
}
function greeting (name) {
if (GUEST_LIST[name]) {
return "Hi I'm " + name + ", and I'm from " + GUEST_LIST[name]
} else {
return "Hi! I'm a guest"
}
}
console.log(greeting('Randy'))
console.log(greeting('The guy from the bus stop'))
To appreciate what I mean here is the working version of your code.
for (let i in x)
{
if (name === x[i])
{
txt = "Hi I'm "+x[i] +", and I'm from " +array[i];
break; // <---- stop the loop here when you find a match
}
else
{
txt = "Hi! I'm a guest";
}
}
return txt;
}
Simple to read and short:
const GUEST_LIST = {
Randy: "Germany",
Karla: "France",
Wendy: "Japan",
Norman: "England",
Sam: "Argentina"
}
function greeting(name){
return (GUEST_LIST[name]) ?
`Hi, I'm ${name} and I'm from ${GUEST_LIST[name]}` :
`Hi! I'm a guest`
}
console.log(greeting("Randy"))
I have a JSON object structured as such:
var theSchools = {
Bradley University: "bru",
Knox College: "knox",
Southern Illinois University Edwardsville: "siue",…
}
What I am trying to achieve is a way of retrieving the key, in this case the school name, by supplying the value, the schools 'code.'
It does not appear that I will be able to have this restructured correctly, i.e.
var theSchools = [
{
schoolName:"Bradley University",
schoolCode: "bru"
}
{
schoolName: "Knox College",
schoolCode: "knox"
}
]
so I'm kind of stuck with what I got.
I know the following code is incorrect, but it's essentially what I want to achieve:
if(getParameterByName("schoolId").length>0){
var schoolid = getParameterByName("schoolId");
var schoolName= theSchools.schoolid;
jQuery("h1").after("<h2>Welcome to <strong>"+schoolName+"</strong></h2>")
}
You can use a for...in loop to loop over each property in the object, and return the property name if the value matches:
var theSchools = {
"Bradley University": "bru",
"Knox College": "knox",
"Southern Illinois University Edwardsville": "siue"
};
function findSchool(code) {
for (var s in theSchools) {
if (theSchools[s] === code)
return s;
}
return null;
}
document.getElementById('school').innerText = findSchool('knox');
<div id="school"></div>
The question is if you really need it this way (see answer #James), here's what you requested:
var theSchools = {
"Bradley University": "bru",
"Knox College": "knox",
"Southern Illinois University Edwardsville": "siue"
}, schoolMap = {};
for (var schoolName in theSchools) {
var code = theSchools[ schoolName ];
schoolMap[ code ] = schoolName;
}
document.body.innerHTML = schoolMap["bru"]; // Bradley University
You don't have to use a for loop to check if property exists. Use hasOwnProperty method.
if (theSchools.hasOwnProperty("Knox College")) {
//do stuff
}
Working example: https://jsfiddle.net/7q9czdpc/
I need to find the key of last property starting with a string
JSON:
var data = {
"admin": "peterson",
"worker": "peter napier",
"housekeeper": "peterson",
"worker": "richard Ben",
"executive": "richard parker",
"executive": "peter alp",
"housekeeper": "richard johny",
"admin": "richardson"
};
I have to write an algorithm which will return the key corresponding to the last occurence of value starting with a string.
Ex: I need to get admin if I call findKey("richard")
I need to get executive if I call findKey("peter")
I have iterated the object using simple for loop as this
for (var key in yourobject) {
console.log(key, yourobject[key]);
}
But I like to know the fastest way of iterating this as my scenario has more than 100000 property.
Just iterate over your data and store each name beginning with your key :
function findkey(name) {
var lg = name.length,
found;
for(var line in data) {
if(data[line].length >= lg && data[line].substring(0,lg) === name) {
found = line;
}
}
return found;
}
Here you go
var findKey = function (string) {
var keyToReturn;
for(key in data){
if(data[key].indexOf(string) === 0)
keyToReturn = key;
}
return keyToReturn;
}
How would you get the value of assocIMG by key matching the key eg
if I have a var 11786 I want it to return media/catalog/product/8795139_633.jpg
var spConfig = {
"attributes": {
"125": {
"id": "125",
"code": "pos_colours",
"label": "Colour",
"options": [{
"id": "236",
"label": "Dazzling Blue",
"price": "0",
"oldPrice": "0",
"products": ["11148"]
}, {
"id": "305",
"label": "Vintage Brown",
"price": "0",
"oldPrice": "0",
"products": ["11786", "11787", "11788", "11789", "11790", "11791", "11792", "11793"]
}]
}
}
};
var assocIMG = // Added - Removed { here, causes issues with other scripts when not working with a configurable product.
{
11786: 'media/catalog/product/8795139_633.jpg',
11787: 'media/catalog/product/8795139_633.jpg',
}
Above is the objects I am working with and below is my current jQuery. Help would be greatly appreciated.
$('#attribute125').change(function() {
var image = $(this).val();
$.each(spConfig.attributes, function() {
prods = $(this.options).filter( function() { return this.id == image; } )[0].products[0];
alert(prods);
});
});
You can use bracket notation to get object members by their keys. You have the variable prods containing a string ("11786"), and the object assocIMG with various keys. Then just use
assocIMG[prods]
to get the property value 'media/catalog/product/8795139_633.jpg' which is associated with that key.
Note that you should always use strings as keys in your object literal, IE does not support numbers there:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg'
};
Another improvement to your script would be not to loop through the spConfig.attributes each time, and potentially execute your action multiple times if an image is contained in more than one attribute. Instead, build a hash object out of it, where you can just look up the respective product id.
var productById = {};
$.each(spConfig.attributes, function() {
$.each(this.options, function() {
var id = this.id;
productsById[i] = this.products[0];
});
});
$('#attribute').change(function() {
var id = this.value;
var prod = productById[id];
var image = assocIMG[prod];
$("#product_img").attr("src", image);
});
You should not use numbers as object keys (in their start). If you want to get the value associated with the 11786 integer key, you will need to use this syntax:
assocIMG["11786"] or assocIMG[11786]
Not
assocIMG.11786
The first thing that you need to do is to create your keys as strings, since you would have:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg',
}
But even doing this, you won't be able to access the field using assocIMG.11786 and the first valid sintax that I presented will still work. The correct approach would be:
var assocIMG = {
id11786: 'media/catalog/product/8795139_633.jpg',
id11787: 'media/catalog/product/8795139_633.jpg',
}
Or
var assocIMG = {
"id11786": 'media/catalog/product/8795139_633.jpg',
"id11787": 'media/catalog/product/8795139_633.jpg',
}
Note that the keys are now starting with letters, not numbers. And now, you will can access the 11786 field as assocIMG.id11786 or assocIMG["id11786"], not assocIMG[id11786]
To Get the Value from object by matching key I ended up with the following
$.each(assocIMG, function(index, value) {
if(index == prods) {
var image_path = value;
$("#product_img").attr("src", image_path);
//alert(image_path);
}
I have an array like this:
var movies = [
{ Name: "The Red Violin", ReleaseYear: "1998", Director: "François Girard" },
{ Name: "Eyes Wide Shut", ReleaseYear: "1999", Director: "Stanley Kubrick" },
{ Name: "The Inheritance", ReleaseYear: "1976", Director: "Mauro Bolognini" }
];
I want to find the location of the movie that's released in 1999.
Should return 1.
What's the easiest way?
Thanks.
You will have to iterate through each value and check.
for(var i = 0; i < movies.length; i++) {
if (movies[i].ReleaseYear === "1999") {
// i is the index
}
}
Since JavaScript has recently added support for most common collection operations and this is clearly a filter operation on a collection, instead you could also do:
var moviesReleasedIn1999 = movies.filter(function(movie) {
return movie.ReleaseYear == "1999";
});
assuming you're not interested in the indexes but the actual data objects. Most people aren't anyways :)
.filter is not supported in all browsers, but you can add it yourself to your code base:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter#Compatibility
Built in? Use loops.
You want to get fancy? Linq to Javascript: http://jslinq.codeplex.com/
Something like:
function findMovieIndices(movies, prop, value) {
var result = [];
for(var i = movies.length; i--; ) {
if(movies[i][prop] === value) {
result.push(i); // personally I would return the movie objects
}
}
return result;
}
Usage:
var indices = findMovieIndices(movies, "ReleaseYear", "1999");
Maybe this gives you some idea for a more generalized function (if you need it).
Since you've also tagged it with jQuery, you could use the 'map' function:
var movies = $.map(movies,function(item,index){
return item.ReleaseYear == 1999 ? index : null;
});
This will return an array of indexes for all movies with the year of 1999. If you wanted the movies themselves as an array:
var movies = $.map(movies,function(item){
return item.ReleaseYear == 1999 ? item : null;
});
If functional style programming is applicable:
_.indexOf(_.pluck(movies, "ReleaseYear"), "1999")
Because it's that simple. The functional toolkit that is underscore.js can be very powerful.
_.indexOf , ._pluck
You'll have to create your own searching function.
Array.prototype.findMovieByYear = function (findYear) {
for (var i = 0; i < this.length; i++) {
// this actually returns the element, maybe you just want
// to return the array index ( the i param )
if (this[i].Release == findYear) return this[i];
}
return null;
// or return -1 or whatever if you want to return the index
};
// now you can call:
movies.findMovieByYear('1998');
// and that should return
{ Name: "The Red Violin", ReleaseYear: "1998", Director: "François Girard" }
Of course, this way of doing it actually affects every array you create.. which is maybe not what you want.. you can create your own array object then ...