JavaScript basics: array or arrays - javascript

I'm trying to learn JavaScript and am going through an exercise where I'm creating a grocery list that populates with a food, quantity, and cost. I cannot seem to pass in multiple variables or make an array of arrays. I tried some other options like "new Object" but I can't get anything off the ground. Give me a clue?
var groceryList = function(food, quantity, price) {
var theItem = [food, quantity, price]
var theList = new Array();
theList.push(theItem)
}
myList = new groceryList("cookie", 2, 1.00)
console.log(myList)

Use this
var groceryList = function(food, quantity, price) {
var theItem = [food, quantity, price]
var theList = new Array();
theList.push(theItem);
return theList;
}
myList = new groceryList("cookie", 2, 1.00)
console.log(myList)

If you want to use objects, then you need to change your thinking a little bit. When you create an object with new then the constructor gets called.
function GroceryList(food, quantity, price) {
this.food = food;
this.quantity = quantity;
this.price = price;
}
GroceryList.prototype.toString = function() {
return this.food + (this.quantity).toString() + (this.price).toString();
}
// lazy array syntax
var GroceryListPool = [];
// popular the array list pool
var list1 = new GroceryList("Butter", 2, 3.999);
GroceryListPool.push(list1);
To iterate the GroceryListPool array:
for(var i = 0; i < GroceryListPool.length; i++) {
var list = GroceryListPool[i];
// list is an object of type GroceryList
// technically it is not a "type", but you know what I mean.
alert(list);
}

That's not even really a Constructor, yet. Check this out.
function groceryList(food, quantity, price){
this.items = {};
if(food !== undefined){
this.items[food] = {quantity:quantity, price:price, total:quantity*price};
}
this.addItem = function(food, quantity, price){
this.items[food] = {quantity:quantity, price:price, total:quantity*price};
}
this.getFood(food){
return this.items[food];
}
this.getQuantity = function(food){
return this.items[food].quantity;
}
this.getTotal = function(food){
return this.items[food].total;
}
this.getItemsByPrice(low, high){
var r = {}, t = this.items;
for(var i in t){
var f = t[i], p = f.price;
if(p >= low && p <= high){
r[i] = f;
}
}
return r;
}
}
var groc = new groceryList('potato', 4, 0.89);
groc.addItem('orange', 10, 1);
console.log(groc.getQuantity('potato'));
console.log(groc.getTotal('orange'));
console.log(groc.getFood('orange').price);
// same as
console.log(groc.getPrice('orange'));
// or
console.log(groc.items.orange.price);
groc.addItem('pear', 200, 0.75);
console.log(groc.getItemsByPrice(0.25, 0.99)); // should be Object with 'potato' and 'pear'

Related

Getting max and min value from array of objects and returning another value associated with the same object. JavaScript

I am having trouble with a task from an education course I am taking, both the highestValShoe and lowestValShoe functions return the same.
I have tried my best with this but I am not understanding where I am going wrong here. I would really appreciate some pointers. Thank you!
//First I will establish an empty array to push() the shoes in later.
shoeArray = [];
//Now I will create a class for the shoes.
class Shoes {
constructor(name, productCode, quantity, valuePerItem) {
this.name = name;
this.productCode = productCode;
this.quantity = quantity;
this.valuePerItem = valuePerItem;
}
//This code will enable us to update the quantity.
updateQuantity(newQuantity) {
this.quantity = newQuantity;
}
}
//Now I will create 5 instances for the class.
converse = new Shoes("Converse", 010405, 3, 55.5);
adidas = new Shoes("Adidas", 030602, 5, 85.0);
nike = new Shoes("Nike", 052656, 2, 165.0);
vans = new Shoes("Vans", 745023, 6, 95.5);
fila = new Shoes("Fila", 034567, 3, 45.0);
//This will push all instances into the shoeArray.
shoeArray.push(converse, adidas, nike, vans, fila);
//This function will enable us to search for any shoe within the array.
function searchShoes(shoeName, shoeArray) {
for (i = 0; i < shoeArray.length; i++) {
if (shoeArray[i].name === shoeName) {
return shoeArray[i];
}
}
}
//This function will enable us to search for the lowest value shoe.
function lowestValShoe (shoeArray) {
for (i=0; i<shoeArray.length; i++){
lowestVal = Math.min(shoeArray[i].valuePerItem)
shoe = shoeArray[i].name
}
return shoe
}
//This function will enable us to search for the highest value shoe.
function highestValShoe (shoeArray){
for (i=0; i<shoeArray.length; i++){
highestVal = Math.max(shoeArray[i].valuePerItem)
shoe1 = shoeArray[i].name
}
return shoe1
}
I tried to return the maximum value 'Shoe' and the minimum value 'Shoe', I thought it was working when I tested the lowestValShoe function, but then when I converted that to maximum, it was returning the same.
I altered the values on one of the shoes to make another one lowest instead, and realised that my lowestValShoe function was not working as intended either.
Both of these functions return 'Fila'
You need to store the object instead only the name for fiinding the min or max value shoe.
Take the first item and iterate from the second to end. Then check if value is greater or smaller and take the item. Later return only the name.
function highestValShoe(shoeArray) {
let shoe = shoeArray[0];
for (let i = 1; i < shoeArray.length; i++) {
if (shoeArray[i].valuePerItem > shoe.valuePerItem) shoe = shoeArray[i];
}
return shoe.name;
}
BTW, please declare all variables. If not, you get global ones and this may lead to funny results. And use semicolons. Always.
//Now I will create a class for the shoes.
class Shoes {
constructor(name, productCode, quantity, valuePerItem) {
this.name = name;
this.productCode = productCode;
this.quantity = quantity;
this.valuePerItem = valuePerItem;
}
//This code will enable us to update the quantity.
updateQuantity(newQuantity) {
this.quantity = newQuantity;
}
}
//This function will enable us to search for any shoe within the array.
function searchShoes(shoeName, shoeArray) {
for (let i = 0; i < shoeArray.length; i++) {
if (shoeArray[i].name === shoeName) return shoeArray[i];
}
}
//This function will enable us to search for the lowest value shoe.
function lowestValShoe(shoeArray) {
let shoe = shoeArray[0];
for (let i = 1; i < shoeArray.length; i++) {
if (shoeArray[i].valuePerItem < shoe.valuePerItem) shoe = shoeArray[i];
}
return shoe.name;
}
function highestValShoe(shoeArray) {
let shoe = shoeArray[0];
for (let i = 1; i < shoeArray.length; i++) {
if (shoeArray[i].valuePerItem > shoe.valuePerItem) shoe = shoeArray[i];
}
return shoe.name;
}
//Now I will create 5 instances for the class.
const
shoeArray = [],
converse = new Shoes("Converse", "010405", 3, 55.5),
adidas = new Shoes("Adidas", "030602", 5, 85.0),
nike = new Shoes("Nike", "052656", 2, 165.0),
vans = new Shoes("Vans", "745023", 6, 95.5),
fila = new Shoes("Fila", "034567", 3, 45.0);
//This will push all instances into the shoeArray.
shoeArray.push(converse, adidas, nike, vans, fila);
console.log(lowestValShoe(shoeArray));
console.log(highestValShoe(shoeArray));
Since you need to rewrite your min and max functions so they won't just use Math.min and Math.max you could use Array.reduce to make them a one liner:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
function lowestValShoe (shoeArray) {
return shoeArray.reduce((prev, curr) => (prev.valuePerItem < curr.valuePerItem ? prev : curr));
}
function highestValShoe (shoeArray){
return shoeArray.reduce((prev, curr) => (prev.valuePerItem > curr.valuePerItem ? prev : curr));
}
Here you can see it live returning Fila and Nike for respectively the min and the max:
//First I will establish an empty array to push() the shoes in later.
shoeArray = [];
//Now I will create a class for the shoes.
class Shoes {
constructor(name, productCode, quantity, valuePerItem) {
this.name = name;
this.productCode = productCode;
this.quantity = quantity;
this.valuePerItem = valuePerItem;
}
//This code will enable us to update the quantity.
updateQuantity(newQuantity) {
this.quantity = newQuantity;
}
}
//Now I will create 5 instances for the class.
converse = new Shoes("Converse", 010405, 3, 55.5);
adidas = new Shoes("Adidas", 030602, 5, 85.0);
nike = new Shoes("Nike", 052656, 2, 165.0);
vans = new Shoes("Vans", 745023, 6, 95.5);
fila = new Shoes("Fila", 034567, 3, 45.0);
//This will push all instances into the shoeArray.
shoeArray.push(converse, adidas, nike, vans, fila);
console.log(lowestValShoe(shoeArray));
console.log(highestValShoe(shoeArray));
function lowestValShoe(shoeArray) {
return shoeArray.reduce((prev, curr) => (prev.valuePerItem < curr.valuePerItem ? prev : curr));
}
function highestValShoe(shoeArray){
return shoeArray.reduce((prev, curr) => (prev.valuePerItem > curr.valuePerItem ? prev : curr));
}

How can I select a Object which has an Array as part of its constructor?

How can I access a certain argument in a Object constructor which is an Array and pick a index in the array to do a calculation with (get the total of all the items for that costumer).
I have been trying to get the price value in the Items Object and add the total for each costumer object in the order Array.
I am selecting them from a selection element in HTML, which is populated in JS.
console.log(costomer[0].order[1]);
I have tried various syntax but when I choose the index of the costumer array I get undefined as the result.
//Waiter Constructor
function Costumer(name, order, total) {
this.name = name;
this.order = [];
this.total = total;
}
//CostomerArray
const costumers = [
new Costumer('Timo'),
new Costumer('Bill')
];
//This is done twice in the same way for the items as well both populate the
//selection element.
custumer.forEach(({ name }) => costumerEl.options.add(new Option(name)));
//Item constuctor
function Item(item, price) {
this.item = item;
this.price = price;
}
//Main food array
const items = [
new Item('Keyboard', 14.50),
new Item('mouse', 10)
];
//This is the function which adds the items to the array when the form is submitted.
const formEl = document.getElementById('mainForm');
formEl.onsubmit = function(e) {
const foodItem = foodMain.options[foodMain.selectedIndex].value;
const costumerName = costumerEl.options[costumerEl.selectedIndex].value;
const costumer = costumer.find(({ name }) => name === costumerName);
if (costomer && itemItem) {
waiter.order.push(itemItem);
console.log(costumers);
};
return false; // prevents redirect/refresh
};
The expected result would be for 'Timo' to order a mouse and keyboard and to add both price arguments in the order array to give a total.
ex.
(2) [Waiter, Waiter]
0: Waiter
name: "Timo"
order: Array(2)
0: "Keyboard (14.5)"
1: "Mouse (10)"
length: 2
__proto__: Array(0)
total: undefined
__proto__: Object
I want to calculate the total of the items that 'Timo' has ordered.
Your question has a lot of problems but i can help you with some of them.
First, you should change Costumer and Item to classes.
//Waiter Constructor
function Costumer(name, order, total){
this.name = name;
this.order = [];
this.total = total;
}
to
//Waiter Constructor
class Costumer {
constructor(name, order, total){
this.name = name;
this.order = [];
this.total = total;
}
}
the same goes to Item
//Item constuctor
class Item {
constructor(item, price) {
this.item = item;
this.price = price;
}
}
and then you can calculate the total price of 'Timo' items like this:
(assuming that 'Timo' will be the first on the customers Array)
var totalPrice = 0;
for(let i = 0; i < costumer[0].order.length; ++i) {
totalPrice += costumer[0].order[i].price;
}

Javascript remove duplicated object from array

i'm having trouble to remove duplicated object from my array
example:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
in this example i have 3 objects, and i want to remove the object that have the duplicated place
Just in case someone wonders: underscore.js solution:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
_.uniq(list, function(item, key, a) {
return item.place;
})
Example Fiddle
A simple one:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
list.forEach(function(i) {
var duplicates = list.filter(function(j) {
return j !== i && j.place == i.place;
});
duplicates.forEach(function(d) { list.splice(list.indexOf(d), 1); });
});
// list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}];
document.write(JSON.stringify(list));
As you added:
i want to remove just one, dont matter wich one
If you want to remove duplicated items and keep only the first occcurence of particular place, you can simply use a simple loop to re-create a new array from the input:
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
var uniqPlace = function(array){
var result = [];
array.forEach(function(el){
if (result.filter(function(n){ return n.place === el.place }).length==0){
result.push(el);
}
})
return result;
}
Output:
uniqPlace(list);
[{"place":"AAA","name":"Me"},{"place":"BBB","name":"You"}]
Try this.
var result = {};
for (i = 0, n = arr.length; i < n; i++) {
var item = arr[i];
result[ item.place + " - " + item.name ] = item;
}
Loop the result again, and recreate the array.
i = 0;
for(var item in result) {
clearnArr[i++] = result[item];
}
Create a object to store the items by their place value, as the new item with the same key will overwrite the old one, this will easily remove all dulplicates.
var list = [{place:"AAA",name:"Me"}, {place:"BBB",name:"You"}, {place:"AAA",name:"Him"}];
var removeDuplicate = function(list) {
var keyStore = {};
var output = [];
// If you want to creata totally new one from old, use
// list = JSON.parse(JSON.stringify(list));
// The above commented out code will create a copy of list, so the items in output will not affect the original ones.
list.forEach(function(item) {
// new one overwrites old one.
keyStore[item.place] = item;
});
var key;
for (key in keyStore) {
output.push(keyStore[key]);
}
return output;
};
console.log(removeDuplicate(list));
3 way to remove duplicate objects from array
let list = [{place:"AAA",name:"Me"},
{place:"BBB",name:"You"},
{place:"AAA",name:"Him"}];
let output1 = Array.from(new Set(list.map(list=>list.place))).map(place=>{
return {
place: place,
name: list.find(a=>a.place===place).name
}
})
console.log('------------------------1st way')
console.log(output1)
let output2 = list.reduce((accumulator, element) => {
if (!accumulator.find(el => el['place'] === element['place'])) {
accumulator.push(element);
}
return accumulator;
},[]);
console.log('------------------------2nd way')
console.log(output2)
const output3 = [];
const map = new Map();
for (const object of list) {
if(!map.has(object.place)){
map.set(object.place, true);
output3.push({
place: object.place,
name: object.name
});
}
}
console.log('------------------------3rd way')
console.log(output3)

array.sort by more than one value

I have an array variable, filled by objects.
I need to sort this array primary by array[i].target; then secondary by array[i].weaponPriority
I can sort an array by one value, but unfortunally i cant grasp how i could refine it further.
Please advice.
var ships = []
function Ship(name, target, priority){
this.name = name;
this.target = target;
this.id = ships.length;
this.weaponPriority = priority;
}
var ship = new Ship("Alpha", 10, 3);
ships.push(ship);
var ship = new Ship("Beta", 10, 1);
ships.push(ship);
var ship = new Ship("Gamma", 10, 3);
ships.push(ship);
var ship = new Ship("Delta", 15, 2);
ships.push(ship);
function log(){
for (var i = 0; i < ships.length; i++){
var shippy = ships[i];
console.log(shippy.name + " ---, targetID: " + shippy.target + ", weaponPrio: " + shippy.weaponPriority);
}
ships .sort(function(obj1, obj2){
...
});
log();
You could try something like this:
function( obj1, obj2 ){
// We check if the target values are different.
// If they are we will sort based on target
if( obj1.target !== obj2.target )
return obj1.target-obj2.target
else // The target values are the same. So we sort based on weaponPriority
return obj1.weaponPriority-obj2.weaponPriority;
}
You will pass this function to the sort.

Filter Array on same name and date

var Array = [{"Name":"Temp","Date":"2014-10-23"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}]
What would be the best way to filter the above array on the following condition.
*If the name is the same, then filter away all the objects with the same name and leave only the object with the latest date left.
All I can think of is to do for loops. Note that Date is a real dateObject and not a string as I have wrote above which means that you can do Date comparisons.
Using Array.reduce(), i was able to get it down to an object containing only Temp and Temp2 with their dates:
var obj = array.reduce(function(base,cur){
if (base[cur.Name]) {
if (base[cur.Name].Date < cur.Date) {
base[cur.Name].Date = cur.Date;
} else {
return base;
}
} else {
base[cur.Name] = cur;
return base;
}
},{});
From there, you can just get the object's values with Object.keys().map():
array = Object.keys(obj).map(function(k){
return obj[k];
});
var array = [{"Name":"Temp","Date":new Date("2014-10-23")},
{"Name":"Temp","Date":new Date("2014-10-22")},
{"Name":"Temp","Date":new Date("2014-10-18")},
{"Name":"Temp","Date":new Date("2014-10-19")},
{"Name":"Temp2","Date":new Date("2014-10-12")},
{"Name":"Temp2","Date":new Date("2014-06-12")}];
var obj = {};
for(var i in array){
if(!obj[array[i].Name] || obj[array[i].Name].getTime() < array[i].Date.getTime())
obj[array[i].Name] = array[i].Date;
}
then if you need it to be an array of objects:
array = [];
for(var name in obj){
array.push({Name: name, Date: obj[name]});
}
var Array = [{"Name":"Temp","Date":"2014-10-23"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}]
var result = {};
Array.forEach(function(item) {
var name = item['Name'];
if(result[name]) {
result[name].push(item['Date']);
} else {
result[name] = [item['Date']];
}
})
Object.keys(result).forEach(function(item) {
result[item] = Math.max.apply(null, result[item]);
})
aggragate the array by name to {Name: 'Temp', Date: ['2014-10-23', '2013-10-32', 'xxxx']}
then get the max date by Math.max.apply
Here you go, Works perfect for any random orders
var Array = [{"Name":"Temp","Date":"2014-10-03"},
{"Name":"Temp","Date":"2014-10-22"},
{"Name":"Temp","Date":"2014-10-18"},
{"Name":"Temp","Date":"2014-10-19"},
{"Name":"Temp2","Date":"2014-10-12"},
{"Name":"Temp2","Date":"2014-06-12"}];
var tempArray = []; //This array will hold your Result Set
var tempArrayName = [];
var tempDate = {};
$.each(Array, function(i, v) {
if(tempArrayName.indexOf(Array[i].Name) < 0){
tempArray.push({ "Name":Array[i].Name,"Date":Array[i].Date});
tempArrayName.push(Array[i].Name);
tempDate[Array[i].Name] = Array[i].Date;
}else{
if( new Date((Array[i].Date))> new Date(tempDate[Array[i].Name])){
$.each(tempArray, function(j, k) {
if(tempArray[j].Name == Array[i].Name){
tempArray[j].Date = Array[i].Date;
}
});
}
}
});
console.log(tempArray);
I'd advise against overwriting the Array object. Anyhow,
one way would be to group the dates using an object:
var data = [
{"Name":"Temp","Date": new Date("2014-10-23")},
{"Name":"Temp","Date": new Date("2014-10-22")},
{"Name":"Temp","Date": new Date("2014-10-18")},
{"Name":"Temp","Date": new Date("2014-10-19")},
{"Name":"Temp2","Date": new Date("2014-10-12")},
{"Name":"Temp2","Date": new Date("2014-06-12")}
];
var name2dates = Object.create(null);
data.forEach(function(thing){
if(!name2dates[thing.Name]){
name2dates[thing.Name] = thing.Date;
}else{
name2dates[thing.Name] = thing.Date > name2dates[thing.Name] ?
thing.Date : name2dates[thing.Name];
}
});
And to create a 'filtered' array from this, if that's what you
need, then:
Object.keys(name2dates).map(function(name){
return {Name: name, Date: name2dates[name]};
});
Is this helpful?
$.grep(Array, function(v) {
return v.Name === "Temp";
}).reduce(function (a, b) { return a.Date > b.Date ? a : b; });

Categories