Array Merge based on two value - javascript

I have an array like:
Name Qty Price
happ 1 50
happ 1 50
happ 1 50
happ 2 10
app 1 50
app 1 50
app 1 50
app 2 10
and I have to convert and merge like that using JavaScript /jquery:
Name Qty Price
happ 3 50
happ 2 10
app 3 50
app 2 10
based on equal name and price
Any help should be appreciated.

I love such a tasks. They are not a difficult one and help to switch myself into working condition.
// Sample data
arr = [{ name: 'happ', qty: 1, price: 50 },
{ name: 'happ', qty: 1, price: 50 },
{ name: 'happ', qty: 1, price: 50 },
{ name: 'harr', qty: 1, price: 50 }];
result = {};
// Summarize array by one walk
arr.forEach(function(k) {
if (!result[k.name + k.price]) {
result[k.name + k.price] = k;
} else {
result[k.name + k.price].qty += k.qty;
}
});
// convert object to array by one walk
var finalResult = [];
for (var key in result) { finalResult.push(result[key]) }

This problem is equivalent to the SQL query:
SELECT name, sum(qty), price
FROM dataObject
GROUP BY name, price
ORDER BY sum(qty) DESC
You can use the native functions .reduce() to aggregrate the data, and then .sort() to sort by qty:
HTML:
<div id="results"></div>
Javascript:
// Sample data
arr = [{ name: 'happ', qty: 1, price: 50 },
{ name: 'happ', qty: 1, price: 50 },
{ name: 'happ', qty: 1, price: 50 },
{ name: 'happ', qty: 2, price: 10 },
{ name: 'app', qty: 1, price: 50 },
{ name: 'app', qty: 1, price: 50 },
{ name: 'app', qty: 1, price: 50 },
{ name: 'app', qty: 2, price: 10 }];
var groupedObjects = arr.reduce(function(res, obj) {
if (!((obj.name + obj.price) in res))
res.__array.push(res[obj.name + obj.price] = obj);
else {
res[obj.name + obj.price].qty += obj.qty;
}
return res;
}, {__array:[]}).__array
.sort(function(a,b) { return b.qty - a.qty; });
// print results for testing
_.each(groupedObjects,function(obj){
var output = '';
_.each(obj,function(val,key){
output += key+': '+val+'<br>';
});
output += '<br>';
$('#results').append(output);
});
Output:
name: happ
qty: 3
price: 50
name: app
qty: 3
price: 50
name: happ
qty: 2
price: 10
name: app
qty: 2
price: 1
Working Demo

Related

Compare two arrays javascript

I'm working on puppeteer in nike website.
I'm getting the sizes and stock and showing it as an array,
{ sku: 72961, skuname: 'Talla: 6 - Color: Azul', quantity: 2 },
{ sku: 72962, skuname: 'Talla: 6.5 - Color: Azul', quantity: 4 },
{ sku: 72963, skuname: 'Talla: 7 - Color: Azul', quantity: 5 },
{ sku: 72964, skuname: 'Talla: 7.5 - Color: Azul', quantity: 7 },
{ sku: 72965, skuname: 'Talla: 8 - Color: Azul', quantity: 6 },
{ sku: 72966, skuname: 'Talla: 8.5 - Color: Azul', quantity: 5 },
{ sku: 72967, skuname: 'Talla: 9 - Color: Azul', quantity: 8 },
{ sku: 72968, skuname: 'Talla: 9.5 - Color: Azul', quantity: 8 },
{ sku: 72969, skuname: 'Talla: 10 - Color: Azul', quantity: 6 },
{ sku: 72970, skuname: 'Talla: 10.5 - Color: Azul', quantity: 4 },
{ sku: 72971, skuname: 'Talla: 11 - Color: Azul', quantity: 1 },
{ sku: 72972, skuname: 'Talla: 11.5 - Color: Azul', quantity: 2 }
]
That is refreshing each 10 seconds so I'd like to find a way that the last array is compared to the previous to know if a new Size or quantity is added
My code
const pagina = "https://nike.cl"
const producto = "/dm0121-400-nike-dunk-low-retro-qs/p"
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900});
while (true) {
await page.goto(pagina + producto, { waitUntil: 'networkidle2' },);
var SKU = await page.evaluate("skuJson_0")
let filter = SKU.skus.filter( d => d.availablequantity > 0)
var SKUfiltered = filter.map(function(d){
return{
sku: d.sku,
skuname: d.skuname,
quantity: d.availablequantity
}})
console.log(SKUfiltered)
await page.waitForTimeout(10000)
I think the best solution is store the SKU data to check if exists previously and if the value are equals.
If the value pass the two checks you could store it in your "SKU register".
As next step, you could make another checks to filter the value. In your case only check if the quantity is zero.
As a complement, if you get many SKU and store a huge maybe you reach the memory limit. So you could remove it if the array is too big. To make that you could create an Array to store the values in order and remove if you reach some limit like 1000 elements.
In the next example, I simulate get the data in each getSKU execution. You must adapt the code to your solution:
// == FAKE DATA ==
let res_i = 0;
const res_data = [
[
{ sku: 1, skuname: "1", quantity: 0 }, // empty
{ sku: 2, skuname: "2", quantity: 1 },
],
[
{ sku: 1, skuname: "1", quantity: 5 },
{ sku: 2, skuname: "2", quantity: 1 }, // same quantity
{ sku: 3, skuname: "3", quantity: 0 }, // empty
],
[
{ sku: 1, skuname: "1", quantity: 0 }, // empty
{ sku: 3, skuname: "3", quantity: 3 },
{ sku: 4, skuname: "4", quantity: 3 },
],
];
// == END FAKE DATA ==
// An array to save the lastest SKU and a Map to store important values
const SKURegLog = [];
const SKURegdata = new Map();
// A funtion to simulate the data
function getSKU() {
const SKU = res_data[res_i++]; // Simulate the incoming data
return SKU.filter((v) => {
// Get the current SKU in the register
const curSKU = SKURegdata.get(v.sku);
// If exists and the quantity is the same, discard
if (curSKU !== undefined && curSKU.quantity === v.quantity) {
return false;
}
// If the SKU not exists in register add to the array
if (curSKU === undefined) {
SKURegLog.push(v.sku);
}
// Include the SKU in the register. If the array reach
// the limit (1000) delete the olders
SKURegdata.set(v.sku, {quantity: v.quantity});
if (SKURegLog.length > 1000) {
const oldSKU = SKURegLog.shift();
SKURegdata.delete(oldSKU);
}
// Check the current quantity
if (v.quantity === 0) {
return false;
}
// Include the SKU
return true;
});
}
console.log(getSKU());
console.log(getSKU());
console.log(getSKU());
console.log("= Register data:");
console.log(SKURegLog);
console.log(SKURegdata);
Output:
1: [ { sku: 2, skuname: '2', quantity: 1 } ]
2: [ { sku: 1, skuname: '1', quantity: 5 } ]
3: [ { sku: 3, skuname: '3', quantity: 3 }, { sku: 4, skuname: '4', quantity: 3 }]
== Register data:
[ 1, 2, 3, 4 ]
Map(4) {
1 => { quantity: 0 },
2 => { quantity: 1 },
3 => { quantity: 3 },
4 => { quantity: 3 }
}

filter array of objects by methods of another array of objects [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am making a food delivery app and I have two different array of objects. One of them is cartItems and the other is foodItems. The arrays can be of different sizes. So what do I want to loop over each array and check
if the ids of both the array match.
Note I want to check if the quantity exists then increment it by the new quantity else simply add a new quantity
check if itemDetails exists in foodItems array and if it exists, check if the price of cartItems matches of that foodItem, then update the cartItems object, else remove them.
if itemDetails does not exist then update the quantity of the item.
Update
If there are two items with similar id and price, the quantities should be added
Here is my cartItems:
let cartItems = [
{ id: 1, price: 120, quantity: 7 },
{ id: 2, price: 70, quantity: 4 },
{ id: 1, price: 70, quantity: 3 },
{ id: 3, price: 60, quantity: 1 },
{id: 1, price: 120, quantity: 2}
];
Here is my foodItems
let foodItems = [
{
id: 1,
name: "chicken",
itemDetails: [
{
price: 120,
details: "2 pcs of chicken biryani"
},
{
price: 70,
details: "1 pcs of chicken biryani"
}
],
},
{
id: 2,
name: "Mutton",
itemDetails: [
{
price: 120,
details: "Two pieces of mutton biryani",
},
{
price: 70,
details: "one pcs of mutton biryani"
},
],
},
{ id: 3, name: "Ice Cream", price: 60 },
];
This is my desired output
let filteredArrayOuput = [
{
id: 1,
name: "Chicken Biryani",
itemDetails: [
{
price: 120,
details: "Two pieces of chicken Biryani",
},
],
quantity: 7,
},
{
id: 2,
name: "Mutton Biryani",
itemDetails: [
{
price: 70,
details: "Two pieces of mutton biryani",
},
],
quantity: 4,
},
{
id: 1,
price: "Chicken Biryani",
quantity: 3,
itemDetails: [
{
price: 70,
details: "Two pieces of Chicken Biryani",
},
],
},
{ id: 3, price: 60, quantity: 1 },
];
This is what I have done till now
const filterFunc = (arr, price) => {
let filtered = arr.filter((item) => {
return item.price == price;
});
return filtered;
};
const filterArray = (arr1, arr2) => {
const filtered = arr2.filter((el) => {
let arr = arr1.find(({ id, quantity, price }) => {
if (el.id === id) {
if (el.itemDetails !== undefined && el.itemDetails.length !== 0) {
let itemDetails = el.itemDetails;
return (
(el.quantity = quantity),
(el.itemDetails = filterFunc(itemDetails, price))
);
} else {
return (el.quantity = quantity);
}
}
});
return arr;
});
return filtered;
};
console.log(filterArray(cartItems, foodItems))
You can check the below code.
Find existingFoodItem from FoodItems array
Find priceObj by comparing price
return new object with price details if itemDetails exists (checking with ?), else without price if no itemDetails exists.
let cartItems = [
{ id: 1, price: 120, quantity: 7 },
{ id: 1, price: 120, quantity: 1 },
{ id: 2, price: 70, quantity: 4 },
{ id: 1, price: 70, quantity: 3 },
{ id: 3, price: 60, quantity: 1 },
];
let foodItems = [
{
id: 1,
name: "chicken",
itemDetails: [
{
price: 120,
details: "2 pcs of chicken biryani"
},
{
price: 70,
details: "1 pcs of chicken biryani"
}
],
},
{
id: 2,
name: "Mutton",
itemDetails: [
{
price: 120,
details: "Two pieces of mutton biryani",
},
{
price: 70,
details: "one pcs of mutton biryani"
},
],
},
{ id: 3, name: "Ice Cream", price: 60 },
];
let result = [];
cartItems.forEach(cart => {
let esitingItem = result.find(r => r.id === cart.id && r.itemDetails.find(i => i.price === cart.price));
if(esitingItem){
esitingItem.quantity += cart.quantity;
return;
}
let existingFoodItem = foodItems.find(food => food.id === cart.id);
if(existingFoodItem){
let priceObj = existingFoodItem.itemDetails?.find(item => item.price === cart.price);
if(priceObj){
result.push({id:cart.id,name:existingFoodItem.name,itemDetails:[{...priceObj}],quantity:cart.quantity});
}
else{
return result.push({id:cart.id,name:existingFoodItem.name,quantity:cart.quantity});
}
}
});
console.log(result);

how to return object from array with highest key values along with name?

As I'm trying to get an object with all the names with the highest values, I am only getting one value and name rather than all existing names with the same highest value? // { name: 'Stephen', total: 85 } 
Any help would be appreciated.
const students = [
{ name: 'Andy', total: 40 },
{ name: 'Seric', total: 50 },
{ name: 'Stephen', total: 85 },
{ name: 'David', total: 30 },
{ name: 'Phil', total: 40 },
{ name: 'Eric', total: 85 },
{ name: 'Cameron', total: 30 },
{ name: 'Geoff', total: 30 }];
const max = Math.max(...students.map(e => e.total))
const result = students.find(student => student.total === max)
console.log(result)//{ name: 'Stephen', total: 85 } 
Use
const result = students.filter(student => student.total == max)
Another solution using a single forEach loop, which returns an array of the top students.
const students = [{ name: 'Andy', total: 40 },{ name: 'Seric', total: 50 },{ name: 'Stephen', total: 85 },{ name: 'David', total: 30 },{ name: 'Phil', total: 40 },{ name: 'Eric', total: 85 },{ name: 'Cameron', total: 30 },{ name: 'Geoff', total: 30 }];
const findTop = (students) => {
let max = 0;
let top = [];
students.forEach(student => {
if (student.total > max) {
max = student.total;
top = [student];
} else if (student.total === max) {
top.push(student);
}
})
return top;
};
console.log(findTop(students));
One pass over the array is absolutely enough to do the job with Array.prototype.reduce():
const students=[{name:'Andy',total:40},{name:'Seric',total:50},{name:'Stephen',total:85},{name:'David',total:30},{name:'Phil',total:40},{name:'Eric',total:85},{name:'Cameron',total:30},{name:'Geoff',total:30}],
result = students.reduce((res,student,idx) => (
!idx || student.total > res[0]['total'] ?
res = [student] :
student.total == res[0]['total'] ?
res.push(student) :
true
, res),[])
console.log(result)
.as-console-wrapper {min-height:100%}
You could take a single loop with reduce by returning the object with the greatest total.
const
students = [{ name: 'Andy', total: 40 }, { name: 'Seric', total: 50 }, { name: 'Stephen', total: 85 }, { name: 'David', total: 30 }, { name: 'Phil', total: 40 }, { name: 'Eric', total: 85 }, { name: 'Cameron', total: 30 }, { name: 'Geoff', total: 30 }]
highest = students.reduce((r, o) => {
if (!r || r[0].total < o.total) return [o];
if (r[0].total === o.total) r.push(o);
return r;
}, undefined);
console.log(highest);

How can i put loop and get values in javascript?

<script>
var data={
Data: {
name: 'aaaa',
number: '0003'
},
values: {
val: '-20.00',
rate: '22047'
},
user: [ '6|1|5', '10|1|15' ]
};
console.log(data);
console.log(data.user.length);
for(var i=0;i<data.user.length;i++) {
console.log(data.user[i]);
}
</script>
Above is my code i want to put loop and get values like this
this is my data user: [ '6|1|5', '10|1|15' ]
but i want to get like this:
userid - 6
roolno - 1
rank - 5
userid - 10
roolno - 1
rank - 15
how can i do this any one help me out ?
A simple map would do it (see plunker):
data.user.map(function(x) {
var parts = x.split('|');
return {
userid: parts[0],
roolno: parts[1],
rank: parts[2]
};
});
This would return you:
[
{
userid: 1,
roolno: 1,
rank: 5
},
{
userid: 10,
roolno: 1,
rank: 15
},
]

Re-arrange a JSON object

I have data that comes from the database looking like:
[
{
ID: 1,
UPC: 11111,
Qty: 1,
Price: 1.99
},
{
ID: 2,
UPC: 11111,
Qty: 2,
Price: 1.99
},
{
ID: 3,
UPC: 22222,
Qty: 1,
Price: 9.99
},
{
ID: 4,
UPC: 11111,
Qty: 3,
Price: 1.99
},
{
ID: 5,
UPC: 22222,
Qty: 9,
Price: 9.99
}
]
Within the page, if they click a button, I need to rearrange it to look like this:
[
{
UPC: 11111,
Qty: 6,
Price: 1.99
},
{
UPC: 22222,
Qty: 10,
Price: 9.99
}
]
How can I convert this? 99% of the time I need the original dataset, so initially returning it like the 2nd dataset is not an option.
TIA.
Using the link posted above in the comments, I managed to make this work. I feel like there is probably a more efficient way using Underscore.js, but since I can't figure it out, this will do.
var tmpItems = {};
for (var i = items.length; i--;)
{
// init an array, if it is not there
tmpItems[it.All[i]['UPC']] = tmpItems[it.All[i]['UPC']] || [];
tmpItems[it.All[i]['UPC']]['Qty'] = (tmpItems[it.All[i]['UPC']]['Qty'] || 0) + (it.All[i]['Qty'] || 0);
tmpItems[it.All[i]['UPC']]['Price'] = (it.All[i]['Price'] || 0);
}
// convert back to an object
var newItems = [];
for (var key in tmpItems)
{
if (tmpItems.hasOwnProperty(key))
{
newItems.push({ 'UPC': key, 'Qty': tmpItems[key]['Qty'], 'Price': tmpItems[key]['Price'] });
}
}

Categories

Resources