Need help in getting as much unique beer as possible - javascript

Let's say I have a bar and cars stop by to pick up beer(s) before heading to the beach. Each car has a trunk size (remainingSum) and each beer has a size (beer.size)
I would like to provide customers with the beer combination choices (AllCombinations) that their car trunk can fit, but unique combinations.
For example, Input:
let Beers = [
{id: 1, size: 4},
{id: 5, size: 1},
{id: 10, size: 0.5},
{id: 11, size: 1},
{id: 12, size: 2},
{id: 13, size: 1},
];
let TrunkSize = 2;
Expected Output
AllCombinations = [ // no duplicates
[{id: 5, size: 1}, {id: 10, size: 0.5}],
[{id: 5, size: 1}, {id: 11, size: 1}],
[{id: 5, size: 1}, {id: 13, size: 1}],
[{id: 10, size: 0.5}, {id: 11, size: 1}],
[{id: 10, size: 0.5}, {id: 13, size: 1}],
[{id: 11, size: 1}, {id: 13, size: 1}],
[{id: 5, size: 1}],
[{id: 11, size: 1}],
[{id: 12, size: 2}],
[{id: 13, size: 1}],
[{id: 10, size: 0.5}],
]
Current Output
AllCombinations = [
[{id: 5, size: 1}, {id: 10, size: 0.5}], // dup a
[{id: 5, size: 1}, {id: 11, size: 1}], // dup c
[{id: 5, size: 1}, {id: 13, size: 1}], // dup d
[{id: 10, size: 0.5}, {id: 5, size: 1}], // dup a
[{id: 10, size: 0.5}, {id: 11, size: 1}], // dup b
[{id: 10, size: 0.5}, {id: 13, size: 1}], // dup e
[{id: 11, size: 1}, {id: 13, size: 1}], // dup f
[{id: 11, size: 1}, {id: 10, size: 0.5}], // dup b
[{id: 11, size: 1}, {id: 5, size: 1}], // dup c
[{id: 13, size: 1}, {id: 5, size: 1}], // dup d
[{id: 13, size: 1}, {id: 10, size: 0.5}], // dup e
[{id: 13, size: 1}, {id: 11, size: 1}], // dup f
[{id: 5, size: 1}],
[{id: 11, size: 1}],
[{id: 12, size: 2}],
[{id: 13, size: 1}],
[{id: 10, size: 0.5}]
]
Current function:
AllCombinations = [];
GetCombinations(currentCombination, beers, remainingSum)
{
if (remainingSum < 0)
return;// Sum is too large; terminate recursion
else {
if (currentCombination.length > 0)
{
currentCombination.sort();
var uniquePermutation = true;
for (var i = 0; i < this.AllCombinations.length; i++)
{
if (currentCombination.length == this.AllCombinations[i].length)
{
for (var j = 0; currentCombination[j] == this.AllCombinations[i][j] && j < this.AllCombinations[i].length; j++); // Pass
if (j == currentCombination.length) {
uniquePermutation = false;
break;
}
}
}
if (uniquePermutation)
this.AllCombinations.push(currentCombination);
}
}
for (var i = 0; i < beers.length; i++) {
var newChoices = beers.slice();
var newCombination = currentCombination.concat(newChoices.splice(i, 1));
var newRemainingSum = remainingSum - beers[i].size;
this.GetCombinations(newCombination, newChoices, newRemainingSum);
}
}

I've edited your code, fixing sort & checking with additional array & stringify:
let Beers = [
{id: 1, size: 4},
{id: 5, size: 1},
{id: 10, size: 0.5},
{id: 11, size: 1},
{id: 12, size: 2},
{id: 13, size: 1},
];
let TrunkSize = 2;
AllCombinations = [];
var combStrings = []
function GetCombinations(currentCombination, beers, remainingSum)
{
if (remainingSum < 0)
return;// Sum is too large; terminate recursion
else {
if (currentCombination.length > 0)
{
currentCombination.sort((a,b)=>{
return a.id > b.id
});
//var uniquePermutation = true;
var tmp = currentCombination.map((cc)=>{
return cc.id;
})
if (combStrings.indexOf(JSON.stringify(tmp)) == -1) {
this.AllCombinations.push(currentCombination);
var tmp = currentCombination.map((cc)=>{
return cc.id;
})
combStrings.push(JSON.stringify(tmp))
}
}
}
for (var i = 0; i < beers.length; i++) {
var newChoices = beers.slice();
var newCombination = currentCombination.concat(newChoices.splice(i, 1));
var newRemainingSum = remainingSum - beers[i].size;
this.GetCombinations(newCombination, newChoices, newRemainingSum);
}
}
GetCombinations([],Beers,TrunkSize)
console.log(AllCombinations,combStrings)

Here's another approach:
let Beers = [
{id: 1, size: 4},
{id: 5, size: 1},
{id: 10, size: 0.5},
{id: 11, size: 1},
{id: 12, size: 2},
{id: 13, size: 1},
];
let TrunkSize = 2;
// get all combinations (stolen from http://stackoverflow.com/questions/5752002/find-all-possible-subset-combos-in-an-array )
function combinations(array) {
return new Array(1 << array.length).fill().map(
(e1,i) => array.filter((e2, j) => i & 1 << j));
}
// filter them out if the summed sizes are > trunksize
var valids = combinations(Beers).filter(function(el) {
return el.reduce(function(a,b){return a+b.size;}, 0) <= TrunkSize;
});
console.log(valids);

To get all possible combinations without duplicates, you can represent your combinations with a set of N bits, where N = # of 🍺.
So you should get a table that looks like this:
000000
000001
000010
000011
000100
000101
000110
000111
...
111111
The 1 tell you which beers are part of that possible combination. Then you just sum their sizes. If you get a sum greater than trunkCapacity, abort that loop.
After the loop, check that the total size of that combination is within the limits and add it to the list of combinations.
function getCombination(beers, trunkSize) {
const beersCount = beers.length;
const combinationsCount = Math.pow(2, beersCount);
const combinations = [];
let i = 0; // Change this to 1 to remove the empty combination that will always be there.
while(i < combinationsCount) {
const binary = i.toString(2);
const bits = Array.prototype.concat.apply(Array(beersCount - binary.length).fill(0), binary.split('').map(parseInt));
const combination = [];
let bit = 0;
let total = 0;
while(bit < beersCount && total <= trunkSize) {
if (bits[bit]) {
const beer = beers[bit];
total += beer.size;
combination.push(beer);
}
++bit;
}
if (total <= trunkSize) {
combinations.push(combination)
}
++i;
}
return combinations;
}
const combinations = getCombination([
{id: 1, size: 4},
{id: 5, size: 1},
{id: 10, size: 0.5},
{id: 11, size: 1},
{id: 12, size: 2},
{id: 13, size: 1},
], 2);
console.log(JSON.stringify(combinations, null, 2));

You could get all combinations and decide which sets match the conditions.
function getCombinations(array, sum, length) {
function fork(i, t) {
var s = t.reduce((a, b) => a + b.size, 0);
if (i === array.length) {
return s <= sum && t.length <= length && result.push(t);
}
fork(i + 1, t.concat([array[i]]));
fork(i + 1, t);
}
var result = [];
fork(0, []);
return result;
}
var beers = [{ id: 1, size: 4 }, { id: 5, size: 1 }, { id: 10, size: 0.5 }, { id: 11, size: 1 }, { id: 12, size: 2 }, { id: 13, size: 1 }],
result = getCombinations(beers, 2, 2);
document.getElementById('out').appendChild(document.createTextNode(JSON.stringify(result, 0, 4)));
<pre id="out"></pre>

Related

How to calculate and create new object value from two different arrays in Javascript

var array1 = [{issueCount: 16, failCount: 38, id: 1},
{issueCount: 15, failCount: 37, id: 2},
{issueCount: 15, failCount: 34, id: 3}];
var array2 = [{id: 1, totalAttempts: 57},
{id: 2, totalAttempts: 59},
{id: 3, totalAttempts: 67},
{id: 4, totalAttempts: 59}];
I have two arrays. From the above arrays, I need to calculate failure Percentage using the (array1. fail count/array2.totalAttempts) * 100 [id is common between two arrays]. And the final array wants in the below format.
outputArray = [{id: 1, issueCount: 16, failCount: 38, percentage: 66.66},
{id: 2, issueCount: 15, failCount: 37, percentage: 62.71},
{id: 3, issueCount: 15, failCount: 34, percentage: 50.74}];
Thanks in advance.
You can achieve this with a simple for loop.
Just check if the id exists in the second array, if so make your calculations.
const array1 = [{issueCount: 16, failCount: 38, id: 1},
{issueCount: 15, failCount: 37, id: 2},
{issueCount: 15, failCount: 34, id: 3}];
const array2 = [{id: 1, totalAttempts: 57},
{id: 2, totalAttempts: 59},
{id: 3, totalAttempts: 67},
{id: 4, totalAttempts: 59}];
const outputArray = [];
array1.forEach(i1 => {
const i2 = array2.find(i => i.id === i1.id);
if(i2) {
outputArray.push({
id: i1.id,
issueCount: i1.issueCount,
failCount: i1.failCount,
percentage: (i1.failCount / i2.totalAttempts) * 100
});
}
});
console.log(outputArray)
You can do:
const array1 = [{issueCount: 16, failCount: 38, id: 1},{issueCount: 15, failCount: 37, id: 2},{issueCount: 15, failCount: 34, id: 3}]
const array2 = [{id: 1, totalAttempts: 57},{id: 2, totalAttempts: 59},{id: 3, totalAttempts: 67},{id: 4, totalAttempts: 59}]
const mergedArrays = Object.values([...array1, ...array2].reduce((a, c) => (a[c.id] = { ...a[c.id], ...c }, a), {}))
const outputArray = mergedArrays
.filter(o => o.issueCount && o.totalAttempts)
.map(({ id, issueCount, failCount, percentage, totalAttempts }) => ({
id,
issueCount,
failCount,
percentage: Math.round(failCount / totalAttempts * 100 * 100) / 100
}))
console.log(outputArray)
Thank you all for your posts. I have also find the solution below.
outputArray = [];
array1.forEach(function(dataItem1, idx) {
var array2Items = array2[idx];
var outputItems = {};
if (dataItem1 && array2Items){
if(dataItem1.id == array2Items.id){
outputItems.id = dataItem1.id;
outputItems.issueCount = dataItem1.issueCount;
outputItems.failCount = dataItem1.failCount;
outputItems.percentage = ((dataItem1.failCount/array2Items.totalAttempts)*100).toFixed(2);
outputArray.push(outputItems);
}
}
});
console.log(outputArray);

How to derive new objects value from two different arrays in Javascript

I have two arrays as below,
var day1 = [{id: 1, type:"20H", cases: 30, fail: 5},
{id: 1, type:"12C", cases: 10, fail: 3},
{id: 1, type:"4B", cases: 20, fail: 8}];
var day5 = [{id: 5, type:"12C" ,cases: 5, fail: 2},
{id: 5, type:"4B", cases: 12, fail: 3},
{id: 5, type:"20H", cases: 20, fail: 6}];
Expecting the below result of array,
var result = [{id: 1, type:"20H", caseCount: 30, failCount: 5, difference: 10, diffPercentage: 50.00},
{id: 1, type:"12C", caseCount: 10, failCount: 3, difference: 5, diffPercentage: 100.00},
{id: 1, type:"4B", caseCount: 20, failCount: 8, difference: 8, diffPercentage: 66.66}];
The logic of difference and diffPercentage as below,
Here, I am not getting how to get the matched value between two arrays and proceed.
if(day1.type === day5.type){
difference = day1.cases - day5.cases;//Here, 30-20 = 10
diffPercentage = ((day1.cases - day5.cases)/(day5.cases)*100).toFixed(2);// 10/20 * 100 = 50.00
}
Tried the following,
result = [];
day1.forEach(function(day1Items, idx){
var day5Items = day5[idx];
var outputElements = {};
if(day1Items && day5Items){
if(day1Items.type == day5Items.type)){ //Here, I am not getting how to get the matched value between two array and proceed.
console.log("Inside if block2"); //it is coming here, because, the if condition going index wise check
outputElements.id = day1Items.id;
outputElements.type = day1Items.type;
outputElements.caseCount = day1Items.cases;
outputElements.failCount = day1Items.fail;
outputElements.difference = day1Items.cases - day5Items.cases;//Here, I need to get the cases value respective type matched
outputElements.diffPercentage = ((day1.cases - day5.cases)/(day5.cases)*100).toFixed(2);
result.push(outputElements);
}
}
});
console.log(result);
You can use a Map to achieve this.
var day1 = [
{ id: 1, type: "20H", cases: 30, fail: 5 },
{ id: 1, type: "12C", cases: 10, fail: 3 },
{ id: 1, type: "4B", cases: 20, fail: 8 }
];
var day5 = [
{ id: 5, type: "12C", cases: 5, fail: 2 },
{ id: 5, type: "4B", cases: 12, fail: 3 },
{ id: 5, type: "20H", cases: 20, fail: 6 }
];
function merge(arr1, arr2) {
const hashMap = new Map();
arr1.forEach((elem) => {
const elemClone = {
...elem,
failCount: elem.fail,
caseCount: elem.cases
};
delete elemClone.fail;
delete elemClone.cases;
hashMap.set(elem.type, elemClone);
});
arr2.forEach((elem) => {
if (hashMap.has(elem.type)) {
const difference = Math.abs(elem.cases -
hashMap.get(elem.type).caseCount);
const diffPercentage = Number(parseFloat((difference / elem.cases)
* 100).toFixed(2));
hashMap.set(elem.type, {
...hashMap.get(elem.type),
difference,
diffPercentage
});
} else {
hashMap.set(elem.type, elem);
}
});
return Array.from(hashMap.values());
}
console.log(merge(day1, day5));
This should work:
var day1 = [{id: 1, type:"20H", cases: 30, fail: 5},
{id: 1, type:"12C", cases: 10, fail: 3},
{id: 1, type:"4B", cases: 20, fail: 8}];
var day5 = [{id: 5, type:"12C" ,cases: 5, fail: 2},
{id: 5, type:"4B", cases: 12, fail: 3},
{id: 5, type:"20H", cases: 20, fail: 6}];
let result = []
day1.forEach(d1 => {
const day5Item = day5.find(d5 => d5.type === d1.type);
if(day5Item){
let difference = d1.cases - day5Item.cases;
let diffPercentage = (difference/day5Item.cases*100).toFixed(2)
result.push({
id:d1.id,type:d1.type,caseCount:d1.cases,failCount:d1.fail,difference,diffPercentage
})
}
});
console.log(result);
Here is the corrected version of your code.
The issue with your code was, you were looping through day1 array with array.forEach and by making use of that index you were selecting matching node from day5 array. Thats worng, This will work only if the arays are in the same order with type. Rather that selecting with var day5Items = day5[idx]; you have to select the node from day5 using Array.find and checking with type. Thil will give you the desired node.
Also there was an error in calculating diffPercentage
Instead of outputElements.diffPercentage = ((day1.cases - day5.cases)/(day5.cases)*100).toFixed(2); It should be outputElements.diffPercentage = ((day1Items.cases - day5Items.cases)/(day5Items.cases)*100).toFixed(2);. day1 and day5 are arrays. You cannot access day1.cases or day5.cases instead it should be day1Items.cases and day5Items.cases
var day1 = [
{ id: 1, type: "20H", cases: 30, fail: 5 },
{ id: 1, type: "12C", cases: 10, fail: 3 },
{ id: 1, type: "4B", cases: 20, fail: 8 }
];
var day5 = [
{ id: 5, type: "12C", cases: 5, fail: 2 },
{ id: 5, type: "4B", cases: 12, fail: 3 },
{ id: 5, type: "20H", cases: 20, fail: 6 },
];
const result = [];
day1.forEach(function(day1Items, idx){
// You cannot simply select with index.
// Instead make use of `Array.find` to select the node from day5 Array with the condition
// var day5Items = day5[idx];
var day5Items = day5.find((node) => node.type === day1Items.type)
var outputElements = {};
if(day1Items && day5Items){
if(day1Items.type == day5Items.type){ //Here, I am not getting how to get the matched value between two array and proceed.
outputElements.id = day1Items.id;
outputElements.type = day1Items.type;
outputElements.caseCount = day1Items.cases;
outputElements.failCount = day1Items.fail;
outputElements.difference = day1Items.cases - day5Items.cases;//Here, I need to get the cases value respective type matched
// Calculation was wrong here
outputElements.diffPercentage = ((day1Items.cases - day5Items.cases)/(day5Items.cases)*100).toFixed(2);
result.push(outputElements);
}
}
});
console.log(result);
Simplified Method
Use Array.reduce
var day1 = [
{ id: 1, type: "20H", cases: 30, fail: 5 },
{ id: 1, type: "12C", cases: 10, fail: 3 },
{ id: 1, type: "4B", cases: 20, fail: 8 },
{ id: 1, type: "49B", cases: 20, fail: 8 }
];;
var day5 = [
{ id: 5, type: "12C", cases: 5, fail: 2 },
{ id: 5, type: "4B", cases: 12, fail: 3 },
{ id: 5, type: "20H", cases: 20, fail: 6 },
];
const result = day1.reduce((acc, curr) => {
const insertNode = { id: curr.id, type: curr.type, caseCount: curr.cases, failCount: curr.fail };
const d5Node = day5.find((node) => node.type === curr.type);
if (d5Node) {
insertNode.difference = curr.cases - d5Node.cases;
insertNode.diffPercentage = (insertNode.difference / d5Node.cases * 100).toFixed(2);
} else {
// Handle the calculation logic here
insertNode.difference = curr.cases;
insertNode.diffPercentage = insertNode.difference * 100;
}
acc.push(insertNode);
return acc;
}, []);
console.log(result);

How to group items so as not to exceed a total amount in JavaScript?

I have an array of n objects in it. Each object has names as id, quantity, price and total. All of these have significance in solving this problem.
How can I create new arrays where sum of all total of their objects doesn't exceed 150.
My array:
let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}]
Expected result:
array1 = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 1, price: 100, total: 100}]
array2 = [{id: 2, quantity: 1, price: 100, total: 100}]
array3 = [{id: 2, quantity: 1, price: 100, total: 100}]
Conditions:
As mentioned, sum of totals in new arrays mustn't exceed 150
value of total must always be product of quantity and price in that object
object must keep dividing itself into new objects with smaller quantities until above conditions are met
quantity must be an integer
i tried this.
const itemsFinals = [];
const maxTotal = 150;
let totalGroup = 0;
for (i = 0; i < itemComprobantes.length; i++) {
if((itemComprobantes[i].total + totalGroup) < maxTotal){
itemsFinals.push(itemComprobantes[i]);
totalGroup += itemComprobantes[i].total;
}
}
let itemComprobantes = [
{id: 1, quantity: 5, price: 10, total: 50},
{id: 2, quantity: 1, price: 100, total: 100},
{id: 3, quantity: 1, price: 100, total: 100},
{id: 4, quantity: 1, price: 100, total: 30},
{id: 5, quantity: 1, price: 100, total: 80}
]
const itemsFinals = {}
const maxTotal = 150
let totalGroup = 0
let group = 1
for (i = 0; i < itemComprobantes.length; i++) {
if((itemComprobantes[i].total + totalGroup) > maxTotal){
group += 1
totalGroup = 0
}
if (itemsFinals['group '+group] === undefined) {
itemsFinals['group '+group] = []
}
itemsFinals['group '+group].push(itemComprobantes[i])
totalGroup += itemComprobantes[i].total
}
console.log(itemsFinals)
Here is my answer base on my comments.
Here is one way to do it. I know its long but give it a try
let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}, {id: 3, quantity: 5, price: 40, total: 200}, {id: 4, quantity: 2, price: 10, total: 20}];
const maxTotal = 150;
let new_arrays = {};
let index = 0;
let final_total = 0;
new_arrays['array_'+index] = [];
for (var obj of array) {
final_total += obj.total;
while (final_total > maxTotal) {
let exceed_value = final_total - maxTotal; // 350 - 150 = 200
let retain_quantity = parseInt((obj.total - exceed_value) / obj.price); // (300 - 200)/100 = 2
let remaining_quantity = obj.quantity - retain_quantity;
if (retain_quantity != 0) {
retain_obj = Object.assign({}, obj);
retain_obj.quantity = retain_quantity;
retain_obj.total = retain_quantity * obj.price;
new_arrays["array_"+index].push(retain_obj);
}
index++;
new_arrays['array_'+index] = [];
new_obj = Object.assign({}, obj, {quantity: remaining_quantity, total: remaining_quantity * obj.price})
new_arrays["array_"+index].push(new_obj);
// console.log(new_obj);
obj = new_obj;
final_total = remaining_quantity * obj.price;
new_arrays['array_'+index].pop(); // if loop is to repeat again
}
new_arrays["array_"+index].push(obj); // prints new and remaining quantities
}
console.log(new_arrays)

Original array changed without any modifications done

I am trying to remove duplicate objects from an array, and keep only the objects which have the highest nb value.
Example:
From this array:
let arr = [
{id: 1, nb: 1},
{id: 1, nb: 4},
{id: 2, nb: 1},
{id: 3, nb: 1},
{id: 1, nb: 2},
{id: 1, nb: 3},
{id: 2, nb: 7},
{id: 2, nb: 8},
];
I am supposed to get this:
arr2 = [
{ id: 1, nb: 4 },
{ id: 2, nb: 8 },
{ id: 3, nb: 1 }
]
The algorithm below is very correct in theory, however I see the original array is modified by the end (see the last console.log(arr) below):
Code:
let arr = [
{id: 1, nb: 1},
{id: 1, nb: 4},
{id: 2, nb: 1},
{id: 3, nb: 1},
{id: 1, nb: 2},
{id: 1, nb: 3},
{id: 2, nb: 7},
{id: 2, nb: 8},
];
// Original array
console.log(arr);
let tmp = {};
for(let i=0; i<arr.length; i++) {
if( !tmp[arr[i].id] ) {
tmp[arr[i].id] = arr[i];
} else {
if (tmp[arr[i].id].nb < arr[i].nb ) {
tmp[arr[i].id].nb = arr[i].nb;
}
}
}
var result = Object.values(tmp);
// This output the desired result
console.log(result);
// Why the original array changed ?
console.log(arr);
This will output:
> Array [Object { id: 1, nb: 1 }, Object { id: 1, nb: 4 }, Object { id: 2, nb: 1 }, Object { id: 3, nb: 1 }, Object { id: 1, nb: 2 }, Object { id: 1, nb: 3 }, Object { id: 2, nb: 7 }, Object { id: 2, nb: 8 }]
> Array [Object { id: 1, nb: 4 }, Object { id: 2, nb: 8 }, Object { id: 3, nb: 1 }]
> Array [Object { id: 1, nb: 4 }, Object { id: 1, nb: 4 }, Object { id: 2, nb: 8 }, Object { id: 3, nb: 1 }, Object { id: 1, nb: 2 }, Object { id: 1, nb: 3 }, Object { id: 2, nb: 7 }, Object { id: 2, nb: 8 }]
Why did the original array changed when there is no processing on it apart from looping?
The original array is updated at last as the objects in your tmp map and arr share the same object reference. So changes made in tmp will be reflected in arr. You can use Object.assign() to make them point to separate reference. Try the following:
let arr = [ {id: 1, nb: 1}, {id: 1, nb: 4}, {id: 2, nb: 1}, {id: 3, nb: 1}, {id: 1, nb: 2}, {id: 1, nb: 3}, {id: 2, nb: 7}, {id: 2, nb: 8}, ];
let tmp = {};
for(let i=0; i<arr.length; i++) {
if( !tmp[arr[i].id] ) {
tmp[arr[i].id] = Object.assign({},arr[i]);
} else {
if (tmp[arr[i].id].nb < arr[i].nb ) {
tmp[arr[i].id].nb = arr[i].nb;
}
}
}
var result = Object.values(tmp);
console.log(result)
Because objects in both the arrays are sharing the same reference.
You will need to update from
tmp[arr[i].id] = arr[i];
to
tmp[arr[i].id] = JSON.parse(JSON.stringify(arr[i]));
let arr = [
{id: 1, nb: 1},
{id: 1, nb: 4},
{id: 2, nb: 1},
{id: 3, nb: 1},
{id: 1, nb: 2},
{id: 1, nb: 3},
{id: 2, nb: 7},
{id: 2, nb: 8},
];
let tmp = {};
for(let i=0; i<arr.length; i++) {
if( !tmp[arr[i].id] ) {
tmp[arr[i].id] = JSON.parse(JSON.stringify(arr[i]));
} else {
if (tmp[arr[i].id].nb < arr[i].nb ) {
tmp[arr[i].id].nb = arr[i].nb;
}
}
}
var result = Object.values(tmp);
console.log(arr); // original array unchanged

lodash method to merge 2 objects of different sizes

Is there any method to merge 2 arrays of objects like this
var a = [{id: 1, val: 1},{id: 2, val: 2},{id: 3, val: 3},{id: 4, val: 4},{id: 5, val: 5}];
var b = [{id: 21, val: 21},{id: 22, val: 22},{id: 23, val: 23}]
//final result should be
c = [
{id:1, val: 1},
{id:21, val: 21},
{id:2, val: 2},
{id:22, val: 22},
{id:3, val: 3},
{id:23, val: 23},
{id:4, val: 4},
{id:5, val: 5}
]
offcourse I can create it by myself, but just want to check whether lodash provide it or not
You could first zip the arrays, flatten the result and then use compact to remove the missing array elements (zip adds them as undefined):
var c = _.compact(_.flatten(_.zip(a,b)))
Or using chaining:
var c = _(a)
.zip(b)
.flatten()
.compact()
.value()
var a = [{id: 1, val: 1},{id: 2, val: 2},{id: 3, val: 3},{id: 4, val: 4},{id: 5, val: 5}];
var b = [{id: 21, val: 21},{id: 22, val: 22},{id: 23, val: 23}]
var c = _(a)
.zip(b)
.flatten()
.compact()
.value()
document.getElementById('results').textContent = JSON.stringify(c);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<pre id="results"></pre>
var a = [{id: 1, val: 1},{id: 2, val: 2},{id: 3, val: 3},{id: 4, val: 4},{id: 5, val: 5}];
var b = [{id: 21, val: 21},{id: 22, val: 22},{id: 23, val: 23}];
// loop through the biggest array and reduce the result (no need for the value we just need the accumulator and the index)
var result = _.reduce(a.length < b.length? b: a, function(res, _, i) {
if(i < a.length) res.push(a[i]); // if there is still elements in a, push the current one
if(i < b.length) res.push(b[i]); // if there is still elements in b, push the current one
return res;
}, []);
console.log(result);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>
In plain Javascript, you could use a function which iterates to the minimum length of both, assembles the values and concat the rest at the end.
function insert(a, b) {
var c = [],
i = 0,
l = Math.min(a.length, b.length);
while (i < l) {
c.push(a[i], b[i]);
i++;
}
return c.concat(a.slice(i), b.slice(i));
}
var a = [{ id: 1, val: 1 }, { id: 2, val: 2 }, { id: 3, val: 3 }, { id: 4, val: 4 }, { id: 5, val: 5 }],
b = [{ id: 21, val: 21 }, { id: 22, val: 22 }, { id: 23, val: 23 }];
console.log(insert(a, b));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ecmascript5 solution using Math.max()(to find the larger array size) and Array.prototype.push() functions:
var a = [{id: 1, val: 1},{id: 2, val: 2},{id: 3, val: 3},{id: 4, val: 4},{id: 5, val: 5}],
b = [{id: 21, val: 21},{id: 22, val: 22},{id: 23, val: 23}],
maxLen = Math.max(a.length, b.length), aLen = a.length, bLen = b.length,
maxList = aLen > bLen ? a : b;
result = [];
for (var i = 0; i < maxLen; i++) {
(i < aLen && i < bLen) ? result.push(a[i], b[i]) : result.push(maxList[i]);
}
console.log(result);

Categories

Resources