How to add the numeric values of properties of a nested array? - javascript

I'm trying to figure out how to make a function that adds the values of the elements chosen by the user and be able to display the results via prompt and console.log. Also, I'm wondering if there is a way to do it in which I don't need to specify the elements selected in order for the function to find within the code which elements were selected and execute the addition function. Because obviously if the list of options were longer I wouldn't want to have to make a new function for each potential combination of selections. As a side note, I guess the same problem would apply to the if statements, would switch statements be the most efficient way to tackle needs for "DRY" code in that instance?
My javascript code: Please assume that the user selects only the first elements of the nested arrays. Also, that term "one" is worth $8.
var selection = new Array (3);
selection[0] = new Array ('$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8');
selection[1] = new Array ('phone1', 'phone2', 'phone3');
selection[2] = new Array ('one', 'two', 'three');
function pickPhone () {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3");
if (yourPhone == selection[1][0]) {
console.log(selection[1][0] + " will cost: " + selection[0][0]);
alert(selection[1][0] + " will cost: " + selection[0][0]);
pickTerm ();
} if (yourPhone == "phone2") {
alert(selection[1][1] + " will cost: " + selection[0][1]);
} if (yourPhone == "phone3") {
alert(selection[1][2] + " will cost: " + selection[0][2]);
}
}
function pickTerm () {
var yourTerm = prompt("pick term: one, two or three?");
if (yourTerm == selection[2][0]) {
alert("Your total so far is: ??");
}
}
pickPhone ();
Any help is greatly appreciated, thank you.

A solution that keeps your arrays
http://jsfiddle.net/OxyDesign/o10ezyun/
JS
var selection = new Array(3);
selection[0] = new Array(1,2,3,4,5,6,7,8);
selection[1] = new Array('phone1', 'phone2', 'phone3');
selection[2] = new Array('one', 'two', 'three');
var firstValue;
function pickPhone() {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3"),
index = selection[1].indexOf(yourPhone);
if(!~index){
pickPhone();
}else{
firstValue = selection[0][index];
alert(selection[1][index] + " will cost: $" + firstValue);
pickTerm();
}
}
function pickTerm() {
var yourTerm = prompt("pick term: one, two or three?"),
index = selection[2].indexOf(yourTerm),
finalValue = '$'+(firstValue+selection[0][index]);
if(!~index){
pickTerm();
}else{
alert("Your total so far is: "+finalValue);
}
}
pickPhone();

I'am not sure what problem you are actually solving.
How long these lists are (phones, costs, etc)?
What type of mapping is set for those items?
For now I'd recommend to merge corresponding values in objects like this:
// item -> cost
var phones = [
{title: 'phone1', cost: '$1'},
{title: 'phone2', cost: '$2'},
{title: 'phone3', cost: '$3'}
],
terms = [
{title: 'one', cost: '$8'},
{title: 'two', cost: '$2'},
{title: 'three', cost: '$3'}
],
phonesListWithCosts = (function(list) {
return list.reduce(function(memo, item) {
return memo + item.title + ': ' + item.cost;
}, '');
}(phones)),
termsList = (function(list) {
return list.reduce(function(memo, item) {
return memo + ', ' + item.title;
}, '');
}(terms)),
findBy = function(array, property, value) {
return array.filter(function(item) {
return item[property] === value;
})[0];
},
getItem = function(list, promptMessage) {
var selectedItemTitle = prompt(promptMessage);
return findBy(list, 'title', selectedItemTitle);
},
getItemCost = function(item) {
return parseInt(item.cost.replace(/\D/g, ''), 10);
},
pickPhone = function() {
var selectedPhone = getItem(phones, 'pick phone: ' + phonesListWithCosts),
firstPhone = phones[0],
message;
if (selectedPhone) {
message = [selectedPhone.title, 'will cost:', selectedPhone.cost].join(' ');
console.log(message);
alert(message);
if (selectedPhone === firstPhone) {
pickTerm(getItemCost(selectedPhone));
}
}
},
pickTerm = function(accumCost) {
var selectedTerm = getItem(terms, 'pick term: ' + termsList),
totalCost,
message;
if (selectedTerm) {
totalCost = accumCost + getItemCost(selectedTerm);
message = 'Your total so far is: $' + totalCost;
alert(message);
}
};
pickPhone();
jsbin demo.

Related

Count duplicate property values of a nested Javascript object

I'm feeding in information in from an API with the format -
Records = { 0: {fields: {name: "nameExample" place: "placeExample"} }
{1: {fields: {name: "nameExample" place: "placeExample"} }
etc etc
I'm looking for a way to count duplicates of the 'place' field in the format: Scotland(4), London(6) etc. where the number is the amount of times it repeats.
The closest I've got as of yet is counting the letters in each place name, but I'm not sure what I'm doing wrong. I think if I can get them in the same array then it would be simple, but when I tried to do that it put each place in a different array.
Also must be vanilla javaScript, no jQuery. Many thanks!
var URL = new Array();
URL[0] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45";
URL[1] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=45";
URL[2] = "https://www.vam.ac.uk/api/json/museumobject/search?q=a&limit=45&offset=90";
var nRequest = new Array();
for (var i=0; i<3; i++){
(function(i) {
nRequest[i] = new XMLHttpRequest();
nRequest[i].open("GET", URL[i], true);
nRequest[i].onreadystatechange = function (oEvent) {
if (nRequest[i].readyState === 4) {
if (nRequest[i].status === 200) {
var data = JSON.parse(nRequest[i].responseText);
var url = 'http://media.vam.ac.uk/media/thira/collection_images/';
for (let key in data.records) {
let value = data.records[key];
let image = value.fields.primary_image_id;
let res = image.substr(0, 6);
document.querySelector(".map").innerHTML += '<div class="' + value.fields.place + ' map"> ' + value.fields.place + ' <br> </div>';
}
} else {
console.log("Error", nRequest[i].statusText);
}
}
//
};
nRequest[i].send(null);
})(i);
};
If thats the data structure you can solve it like so:
const Records = [
{fields: {name: "nameExample", place: "placeExample"}},
{fields: {name: "nameExample", place: "placeExample"}}
];
const result = Records.reduce((acc, {fields}) => {
if(acc[fields.place]) acc[fields.place]++;
else acc[fields.place] = 1;
return acc;
}, {})
console.log(result);
You can use the reduce function to convert the array data.records to an object with the place as key and number of occurrences as value.
data.records.reduce((accum, currVal) => {
if (!(currVal.fields.place in accum)){
accum[currVal.fields.place] = 0;
}
accum[currVal.fields.place] += 1;
return accum;
}, {});

How to find duplicated title values in a map

I'm new to Javascript, come from Java, this is less intuitive for me.
I would like to check for duplication of the title value and concatenate to the duplicated title the producer name
My idea is to sort the values and then check each one with is next for duplication
Can you suggest me how to implement this kind of solution?
function getItems(itemKeys, itemSortOrders, itemsMap)
{
var items = _.map(itemKeys, function(itemKey, index) {
var item = itemsMap[itemKey];
return _.extend({
key: itemKey,
title: item.title,
imageURL: item.imageURL,
formattedPrice: utils.formatMoney(item.price),
producerKey: item.producerKey,
producerTitle: item.producerTitle,
allowOrder: true,
sortOrder: itemSortOrders[index]
}, calculateItemDetails(item.deliveryDayAvailable, item.deliveryDayStatus, item.deliveryDayUsageCount));
});
items = _.compact(items);
return items;
}
Thanks
You can test if item have duplicates with this function, it use filter to find the same items and check if the length is larger then 1.
function haveDuplicates(itemKeys, itemsMap, itemKey) {
var item = itemsMap[itemKey];
var dups = itemKeys.filter(function(key) {
return itemsMap[key] == item;
});
return dups.length > 1;
}
var itemsMap = {
'foo': 'Lorem',
'bar': 'Lorem',
'baz': 'Ipsum',
'quux': 'Dolor'
};
var output = document.getElementById('output');
var itemKeys = Object.keys(itemsMap);
itemKeys.map(function(key) {
output.innerHTML += itemsMap[key] + ' ' +
(haveDuplicates(itemKeys, itemsMap, key) ? 'have' : 'don\'t have') + '\n';
});
<pre id="output"></pre>
SO this is what i did eventually and this worked
var duplicateMap = {};
_.each(itemsMap, function(item) {
var title = item.title.trim();
if (duplicateMap[title]) {
duplicateMap[title] = 2;
}
else {
duplicateMap[title] = 1;
}
});

Why isn't my program assigning variables to the object, and then calculating from it?

This assignment is to take a pizza order and build one. Once the pizza is assembled, it should calculate the total cost of the pizza and spit out the total answer. I've played around on JsFiddle.net for two days now and can't figure out why it won't get past the interrogate function and move on to the calculate. I've entered in a couple alert statements here and there and still can't figure out what's going on. My best guess is either that 'myPizza' properties are not being assigned or that they are not being shared by the other functions. I know the second possibility could not be true because 'myPizza' is a global object with global properties.
recycle = true;
var ingrediants = ['pepperoni ', 'sausage ', 'avocado ', 'chicken ', 'mushrooms ', 'anchovies ', 'bacon ', 'pineapple ', 'beeswax '];
var toppings=[];
var i = -1;
var myPizza= {
size:"",
toppings:[],
stuffCrust:false,
sodaSide: false
};
var greeting = function () {
wantPizza = prompt("Hello! Welcome to Sean's Pizza Shack! Would you like to order a pizza?(Yes or No?)").toLowerCase();
if (wantPizza === 'yes') {
return true;
} else {
alert("Okay then, Get out of my pizza shop because I have customers waiting");
return false;
}
};
var interrogate = function () {
myPizza.size = prompt("Okay sir/Ma'am, Would you like a Small, Medium, Large, or extra Large?(XL)").toLowerCase();
myPizza.toppings = prompt("Alright! So what would you like on your " + myPizza.size + " pizza?" + " We have " + ingrediants).toLowerCase();
do {
i = i + 1;
myPizza.toppings+= toppings[i] =prompt(ingrediants + " Please type one ingrediant at a time to add to your pizza! or you may enter 'ALL' to add all toppings or press OK without entry to stop adding toppings").toLowerCase();
} while (toppings[i] !== "");
//LOOP TO DECIDE IF NEED TO PUSH ALL INGREDIENTS
for (k = 0; k <toppings.length; k++) {
if (toppings[k] === 'all') {
toppings = [];
toppings.push(ingrediants);
} else {
toppings.length -= 1; // IF NOT ALL INGREDIENTS, SUBTRACT '' FROM ADD INGREDIENTS //LOOP
}
}
alert("So you would like " + myPizza.toppings + " on your pizza!");
alert("Okay so i have a " + myPizza.size + " pizza, with " + myPizza.toppings + "!");
myPizza.stuffCrust = prompt("Do you want your pizza to have extra delicious stuffed cheesy crust?($4.00)").toLowerCase();
if(myPizza.stuffCrust==='yes') {
myPizza.stuffCrust=true;
}
myPizza.sodaSide = prompt("Would you like a 2 Liter soda with that for an extra $2.00?");
if(myPizza.sodaSide=== yes) {
myPizza.sodaSide=true;
}
alert(myPizza.sodaSide);
alert(myPizza.toppings);
alert(myPizza.stuffCrust);
alert(myPizza.toppings.length);
};
var up= {
total:0,
Sm:9.00,
Med:12.00,
Lrg: 15.00,
XL: 18.00,
Top: myPizza.toppings.length*1.00,
Stuff:4.00,
Soda: 2.00,
add: function(input) {
total+=input;
}
};
var calculate= function() {
switch(myPizza.size) {
case 'small': up.add(up.Sm);break;
case 'medium': up.add(up.Med);break;
case 'large': up.add(up.Lrg);break;
case 'XL': up.add(up.XL);break;
}
if(myPizza.toppings.length>0) {
up.add(up.Top);
} if (myPizza.stuffCrust) {
up.add(up.Stuff);
} if (myPizza.sodaSide) {
up.add(up.Soda);
}
alert("Okay, looks like your order comes to "+ up.total);
};
var main= function () {
if (greeting() === true) {
interrogate();
calculate();
}
};
main();
in the statement:
if(myPizza.sodaSide=== yes) {
myPizza.sodaSide=true;
}
you need to have yes in quotes:
if(myPizza.sodaSide=== 'yes') {
myPizza.sodaSide=true;
}

Change select options in forEach loop

I have the following test code:
ID = {
CreatedBy: { id: 'createdBy' },
ModifiedBy: { id: 'modifiedBy' }
}
Profile = {
All: { text: 'All', val: 0 },
Sys: { text: 'system_system#system.com', val: 1 },
Test: { text: 'test_user#live.com', val: 2 }
}
changeSelect(dataId: EnumElement[], params: UserEnum[]) {
dataId.forEach((data) => {
params.forEach((elem) => {
var label = data.id+ ' - Check option changed to - ' + elem.text;
it(label, () => {
return element(by.xpath('//select[#id="' + data.id + '"]/option[#value = "' + elem.val + '"]')).click();
});
});
}
In my test I am calling the changeSelect() function with parameters like such:
changeSelect([ID.CreatedBy, ID.ModifiedBy], [Profile.Sys, Profile.Test]);
As expected my changeSelect() function will output:
createdBy - Check option changed to - system_system#system.com
createdBy - Check option changed to - test_user#live.com
modifiedBy - Check option changed to - system_system#system.com
modifiedBy - Check option changed to - test_user#live.com
But this is not the output that I want. How can I tweak my loop to achieved the output below?
createdBy - Check option changed to - system_system#system.com
modifiedBy - Check option changed to - test_user#live.com
Why not use a simple for?
changeSelect(dataId, params) {
for(i = 0; i < dataId.length; i++){
var data = dataId[i];
var elem = params[i];
var label = data.id + ' - Check option changed to - ' + elem.text;
it(label, () => {
return element(by.xpath('//select[#id="' + data.id + '"]/option[#value = "' + elem.val + '"]')).click();
}
}
}

Dynamic Concatenation in Javascript Array

Let's say I have an array of data and a variable (or multiple variables)
var i = 1;
var arr = {
1: ['whatever' + i,'there are ' + i + ' dogs in the yard.', etc],
}
Is there a way to dynamically update the variable(s) in the array later on in a function?
So
function start() {
i++;
alert(arr[1][0]);
}
Would output "whatever2" instead of "whatever1"
You could have an array and push() stuff you need, but when the string is made, it won't change anymore.
var array = ['whatever',i,'there are ',i,' dogs in the yard.'];
array.push('more stuff');
array.push('even more stuff');
var string = array.join('')
//string = 'whatever[whatever "i" is during join]there are[whatever "i" is during join]dogs in the yard.more stuffeven more stuff'
You could use functions instead:
var i = 1;
var arr = {
1: [
function() { return 'whatever' + i },
function() { return 'there are ' + i + ' dogs in the yard.' },
function() { return 'etc' }
],
}:
Which would change your calls to:
function start() {
i++;
alert(arr[1][0]());
}
Try this code:
var arr = function(i){
return {
1: ['whatever' + i,'there are ' + i + ' dogs in the yard.', etc],
}
}
var anyNumber = 1;
var updatedVar = arr(anyNumber);

Categories

Resources