I have issues removing items from an array based on matched value. I have an array of object like below:
$scope.listOfItems = [
{productID : 1, weight: 3.5, price: 5},
{productID : 2, weight: 4.5, price: 8},
{productID : 3, weight: 1.5, price: 9},
{productID : 4, weight: 2.5, price: 3},
{productID : 5, weight: 7.5, price: 1}
];
And I want to remove items based on an array of productID, like below:
$scope.deleteList = [1,3];
Now I try to use two loops to check if the productID if each product is the same with any productID in the deleteList.
angular.forEach($scope.listOfItems , function(value, key){
var tmp_productID = value.productID ;
var index = key;
angular.forEach($scope.deleteList, function(value,key){
if(tmp_productID === value){
$scope.listOfItems .splice(index ,1);
}
});
});
console.log($scope.listOfItems);
The problem of this is, after it deletes the one with index1, the index3 will be index2, thus it will delete product2 and product5 instead of product2 and product4, which is wrong. Also the performance will be bad if I have a large number of objects in the array and I want to delete half of them. Any idea that I can delete the right record and improve the performance if possible?
Working jsfiddle
http://jsfiddle.net/Lvc0u55v/10726/
You could iterate in reverse, that way the splicing won't affect the previous indices
var $scope = {};
$scope.listOfItems = [{
productID: 1,
weight: 3.5,
price: 5
}, {
productID: 2,
weight: 4.5,
price: 8
}, {
productID: 3,
weight: 1.5,
price: 9
}, {
productID: 4,
weight: 2.5,
price: 3
}, {
productID: 5,
weight: 7.5,
price: 1
}];
$scope.deleteList = [1, 3];
for ( var i = $scope.listOfItems.length; i--; ) {
if ( $scope.deleteList.indexOf( $scope.listOfItems[i].productID ) !== -1 ) {
$scope.listOfItems.splice(i ,1);
}
}
console.log($scope.listOfItems);
.as-console-wrapper {top: 0; max-height: 100%!important}
Related
How to verify with i have only 2 or 3 numbers inside this?
without this ----> if(Array.includes(1) && !Array.includes(3))
const servicesTest: IServices[] = [
{
id: '1',
name: 'Hair',
price: 25,
icon: 'https://cdn-icons-png.flaticon.com/512/7478/7478480.png'
},
{
id: '2',
name: 'Beard',
price: 20,
icon: 'https://cdn-icons-png.flaticon.com/512/7578/7578754.png'
},
{
id: '3',
name: 'Eyebrow',
price: 15,
icon: 'https://cdn-icons-png.flaticon.com/512/2821/2821012.png'
}
]
if the client choose hair + beard this will be 40 not 45.
I´m doing this:
const name = findServices.map(services => services.name)
if (name.includes('Hair') && name.includes('Beard') && !name.includes('Eyebrown')) {
return (
setTotalDay(prevState => prevState + 40),
setTotalMonth(prevState => prevState + 40)
)
}
I would create an array of discounts like this:
const discounts = [{
price: 30,
ids: [1, 2],
}];
Then check if the array has only discounted items like this:
array.length === discount.ids.length && array.every((item) => discount.ids.includes(item.id))
const discounts = [{
price: 30,
ids: [1, 2],
}];
const discounted = [{
id: 1,
name: 'Hair',
price: 20,
},
{
id: 2,
name: 'Beard',
price: 30,
},
];
const fullPrice = [{
id: 1,
name: 'Hair',
price: 20,
},
{
id: 2,
name: 'Beard',
price: 30,
},
{
id: 3,
name: 'Tea',
price: 30,
},
];
console.log("discounted", getTotal(discounted));
console.log("full price", getTotal(fullPrice));
function getTotal(array) {
for (const discount of discounts) {
if (
array.length === discount.ids.length &&
array.every((item) => discount.ids.includes(item.id))
) {
return discount.price;
}
}
return array.reduce((sum, item) => sum + item.price, 0);
}
answering your question before the edit.
Assuming we have this array
const Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
Let's say we want to check if values 2 and 3 exist.
We store the values in an array let toCheck = [2,3];
We can use function every to loop all the elements of toCheck array against the Array const
Example Follows:
const Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let toCheck = [1,2];
const allExist = toCheck.every(value => {
return Array.includes(value);
});
Hope it helps.
As you can see, the keys are now the name of the items and the corresponding value is another object consisting of two keys - quantity and price.
var itemsToBuy = {
milk: {
quantity : 5,
price: 20
},
bread: {
quantity : 2,
price: 15
},
potato: {
quantity : 3,
price: 10
}
}
I tried but I am getting only undefined output.
Want to get data such like :
['milk', 'bread', 'potato']
[20, 15, 10]
const object1 = {
milk: {
quantity : 5,
price: 20
},
bread: {
quantity : 2,
price: 15
},
potato: {
quantity : 3,
price: 10
}
}
console.log(Object.entries(object1).map(([key,value])=> value.price))
Solution
With Object.keys() you can get the keys of your Object as an array. -> ['milk', 'bread', 'potato']
With Object.entries() in combination with map() you can get the values of the price property as an array. -> [20, 15, 10]
Example:
var itemsToBuy = {
milk: {
quantity : 5,
price: 20
},
bread: {
quantity : 2,
price: 15
},
potato: {
quantity : 3,
price: 10
}
}
const keys = Object.keys(itemsToBuy);
const val = Object.entries(itemsToBuy).map((element)=> element[1].price)
console.log(keys);
console.log(val);
for names:
Object.keys(itemsToBuy) //["milk", "bread", "potato"]
and for prices:
Object.entries(itemsToBuy).map((el)=> el[1].price)//[20, 15, 10]
To get object keys you can use: Object.keys()
let keys = Object.keys(itemsToBuy) // ["milk", "bread", "potato"]
And for the nested values you can get 1st all values
let values = Object.values(itemsToBuy) // [{quantity : 5, price: 20}, {quantity : 2, price: 15}, {quantity : 3, price: 10}]
And then map to return the new array with elements you want to extract ex.price:
let price = values.map(value => value.price) // [20, 15, 10]
It's such an easy task, but somehow I'm stuck. I have an array of objects of product items that looks like this:
[{id: 1, price: 30, quantity: 2}, {id: 2, price: 20, quantity: 4}, {id: 3, price: 10, quantity: 2}]
I need to count the total price of all items, which should be: the price of a specific product multiplied by quantity and the same for previous products. Example: (30*2)+(20*4)+(10*2)
My code looks like this:
items.forEach(function (item) {
let sum = item.price * item.quantity;
console.log(sum);
});
The output looks like:
60
80
20
But I need to count the total which should be 160 and render it to the page and somehow I can't figure out the way to do that
The Array.prototype.reduce() method is best suited for operations like this (sum total).
In my answer below, sum is the accumulator and is initially set to 0. The accumulator is the value previously returned by the callback. The { price, quantity } is object destructering of the current value.
const sumTotal = arr =>
arr.reduce((sum, { price, quantity }) => sum + price * quantity, 0)
const data = [
{ id: 1, price: 30, quantity: 2 },
{ id: 2, price: 20, quantity: 4 },
{ id: 3, price: 10, quantity: 2 },
]
const total = sumTotal(data)
console.log(total) // 160
Here is a similar example.
You are close to getting the answer. I modified slightly your code and get the expected result. See below.
const items = [{id: 1, price: 30, quantity: 2}, {id: 2, price: 20, quantity: 4}, {id: 3, price: 10, quantity: 2}];
const sumItems = () => {
let sum = 0;
items.forEach(function(item) {
let calculation = item.price * item.quantity;
sum += calculation;
})
console.log(sum);
};
sumItems();
let items = [
{id: 1, price: 30, quantity: 2},
{id: 2, price: 20, quantity: 4},
{id: 3, price: 10, quantity: 2}
]
let total = items.reduce((sum,item) => sum + item.price * item.quantity, 0);
console.log(total);
var products =[{id: 1, price: 30, quantity: 2}, {id: 2, price: 20, quantity: 4}, {id: 3, price: 10, quantity: 2}]
console.log(products.map(x=> x.price*x.quantity).reduce((a, b) => a + b, 0))
If you can use an external library, I suggest using the sumBy method from lodash library
Example:
_.sumBy(items, function(item) { return item.price * item.quantity; });
I need to filter this object array by minimum value of 'rest' attribute. This is an one way to do it. Is there any other ways ?
'data' variable is a result of chained function. Is there any other way to do this without calling 'data' variable again inside Math.min() function.
let data =
[ { size: 5, qty: 2, rest: 0 },
{ size: 2, qty: 5, rest: 0 },
{ size: 1, qty: 10, rest: 0 },
{ size: 3, qty: 3, rest: 1 },
{ size: 4, qty: 2, rest: 2 } ]
let result = data.filter(e=> e.rest === Math.min(...data.map(f=>f.rest) ) );
console.log(result);
// result is
//[ { size: 5, qty: 2, rest: 0 },
// { size: 2, qty: 5, rest: 0 },
// { size: 1, qty: 10, rest: 0 }]
The easiest way is to pull the min function out of the filter like this:
let min = Math.min(...data.map(item => item.rest))
This is much more efficient as we are no longer loop over the data to find the min for every iteration of the filter.
We now have n * 2 passes instead of n^2 passes. (n is the size of your data set, 5 in this case)
Full example below:
let data = [
{ size: 5, qty: 2, rest: 0 },
{ size: 2, qty: 5, rest: 0 },
{ size: 1, qty: 10, rest: 0 },
{ size: 3, qty: 3, rest: 1 },
{ size: 4, qty: 2, rest: 2 }
]
let min = Math.min(...data.map(item => item.rest))
let result = data.filter(item => item.rest === min)
console.log(result)
Hope this helps!
Lloyd
data.map inside of data.filter is O(N^2); for an O(N) solution, iterate through data ahead of time to calculate the minimum, then filter by that minimum:
let data =
[ { size: 5, qty: 2, rest: 0 },
{ size: 2, qty: 5, rest: 0 },
{ size: 1, qty: 10, rest: 0 },
{ size: 3, qty: 3, rest: 1 },
{ size: 4, qty: 2, rest: 2 } ];
const minRest = Math.min(...data.map(({ rest }) => rest));
let result = data.filter(({ rest }) => rest === minRest);
console.log(result);
imo. the simplest/best solution is the one #CertainPerformance gave you.
Just wanted to add another solution with linear runtime (that truly iterates only once over the Array)
let data = [
{ size: 5, qty: 2, rest: 0 },
{ size: 2, qty: 5, rest: 0 },
{ size: 1, qty: 10, rest: 0 },
{ size: 3, qty: 3, rest: 1 },
{ size: 4, qty: 2, rest: 2 }
];
let result = data.reduce((result, item) => {
let minRest = result.length? result[0].rest: item.rest;
if (item.rest < minRest) {
minRest = item.rest;
result.length = 0;
}
if (item.rest === minRest) {
result.push(item);
}
return result;
}, []);
console.log(result);
#mathieux51 got me another idea how you can do this inside a method chain, but the readability/clarity/intention is not as good as with the other approaches:
let data = [
{ size: 5, qty: 2, rest: 0 },
{ size: 2, qty: 5, rest: 0 },
{ size: 1, qty: 10, rest: 0 },
{ size: 3, qty: 3, rest: 1 },
{ size: 4, qty: 2, rest: 2 }
];
let result = data.sort((a, b) => a.rest - b.rest)
.filter((item, index, array) => item.rest === array[0].rest);
console.log(result);
It sounds like you want to sort the list. I would do it as following:
const result = data.sort((a, b) => a.rest - b.rest)
Get Min or Max
Since no one mentioned this method I will update it here.
myArray.sort(function (a, b) {
return a.rest - b.rest
})
var min = myArray[0],
max = myArray[myArray.length - 1]
It has good readability/clarity/intentions.
I have to filter an array of objects to get certain values based on an another array and distinct also
Data
var value:any[]
var inventory = [
{id: 1, quantity: 2, GroupId: 1},
{id: 2, quantity: 0, GroupId: 2},
{id: 1, quantity: 2, GroupId: 1}
];
//data from db
value = [1,2]
My code
var data = this.inventory .filter(x => x.GroupId == this.value );
Not able to get the filtered data, but returning empty array. Thanks in advance
In your code you are comparing GroupId with an array. You should check if array contains GroupId instead.
Here is how to do it:
var data = this.inventory.filter(x => value.includes(x.GroupId));
For better support you can replace Array.prototype.includes with Array.prototype.indexOf:
var data = this.inventory.filter(x => value.indexOf(x.GroupId) !== -1);
If you want to distinct by the id field here's a solution:
var inventory = [
{id: 1, quantity: 2, GroupId: 1},
{id: 2, quantity: 0, GroupId: 2},
{id: 1, quantity: 2, GroupId: 1}
];
var value = [1,2]
var data = inventory.filter(x => value.indexOf(x.GroupId)>-1).filter((elem1, pos, arr) => arr.findIndex((elem2)=>elem2.id === elem1.id) === pos);
console.log(data);
JSFiddle example: https://jsfiddle.net/7xnybhLv/1/
You should be using includes
console.log([
{id: 1, quantity: 2, GroupId: 1},
{id: 2, quantity: 0, GroupId: 2},
{id: 3, quantity: 2, GroupId: 1}
].filter(x => [1,2].includes(x.id)));
You could use the variable directly and use Array#includes.
var inventory = [{ id: 1, quantity: 2, GroupId: 1 }, { id: 2, quantity: 0, GroupId: 2 }, { id: 3, quantity: 2, GroupId: 1 }],
value = [1, 2],
data = inventory.filter(({ GroupId }) => value.includes(GroupId));
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }