How to derive new objects value from two different arrays in Javascript - 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);

Related

Collect distances (and restore path) from 1 point to all others in a graph

Problem:
I have a weighted graph. I want to get distance from definite point to all other points in the graph.(and then get path to them)
I used modified dijkstra algorithm
So, here is code:
var get_path = function(graph, a) {
// declaration
let cache, i, v, queue, node, links, root,
j, link, c, n, d, max, w, L = graph.length;
// initialization
cache = Array(L);
i = L;
while (--i >= 0) {
v = graph[i];
cache[v.id] = {
id: v.id,
distance: Infinity,
links: v.links,
prev: null,
};
}
root = cache[a];
root.distance = 0;
queue = [root];
// processing
i = 0;
while (i < queue.length) {
node = queue[i];
links = node.links;
j = links.length;
while (--j >= 0) {
link = links[j];
c = cache[link.id];
d = node.distance + link.weight;
if (d < c.distance) {
c.prev = node;
c.distance = d;
queue.push(c);
}
}
i++;
}
return cache;
}
Graph format is:
graph = [
{
id: 1,
links: [
{
id: 2,
weight: 1,
},
{
id: 3,
weight: 1,
},
],
},
{
id: 2,
links: [
{
id: 1,
weight: 1,
},
{
id: 4,
weight: 2,
}
]
},
{
id: 3,
links: [
{
id: 1,
weight: 1,
},
{
id: 4,
weight: 3,
}
]
},
{
id: 4,
links: [
{
id: 2,
weight: 2,
},
{
id: 1,
weight: 1,
},
{
id: 3,
weight: 3,
},
{
id: 5,
weight: 1,
}
]
},
{
id: 5,
links: [
{
id: 4,
weight: 1,
}
]
}
]
Performance:
In my PC this algorithm works with graph of ~160 vertices and ~350 edges about 0.03-0.06ms. But I need faster!
You can measure performance on your PC here
Question:
How to make this code (function get_path()) faster? Is it possible on JavaScript? If I should change the format of graph to make algorithm faster it's not a problem.
Or I exhausted possibilities of JavaScript?

In Javascript, how do I tell array.filter() to duplicate element objects in the new array?

So simplified code.
var a = [
{ name: "first", num: 1 },
{ name: "first", num: 2 },
{ name: "first", num: 3 },
{ name: "first", num: 4 },
{ name: "first", num: 5 },
{ name: "first", num: 6 },
{ name: "first", num: 7 },
{ name: "first", num: 8 },
{ name: "first", num: 9 }
];
var b = a.filter(function(el) {
return el.num % 2 == 0;
});
console.log("a1", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b1", b); // [20, 40, 60, 80]
for (let i = 0; i < b.length; i++) {
b[i].num = b[i].num * 10;
}
console.log("a2", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b2", b); // [20, 40, 60, 80]
My new understanding is the array element contains a reference to an object, not the object. What are some ways to get those objects duplicated?
Filter, then build new objects from the filtered array and put the new things in a new array?
Use some method I'm not currently familiar with?
Redesign the code to stop using objects in an array?
Also, what's up with console.log() showing the variables have changed when placed before the for loop?
If you wish to duplicate the objects inside the array, you should use the map function.
var b = a.filter(val => val.num %2 === 0).map(val => Object.assign({}, val, { num: val.num * 10}));
The map function will return a new array with the value returned from the function. In this example, we are creating a new object Object.assign({}) and duplicating the existing object while changing the num field.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
If you want to clone objects you will need a clone function, I use this function
const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;
You can then clone the array with
let c = clone(b);
Which will be a new array where each object is a new clone.
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
var b = a.filter(function(el){return el.num%2==0 });
const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;
let c = clone(b);
console.log(b[0] === c[0]);
Yes, elements of Array a are all pointers. so you need to use Object.assign (as many says)
and other solution with array reduce usage (see Adrian Brand comment)
var a = [ { name: 'first', num: 1 }
, { name: 'first', num: 2 }
, { name: 'first', num: 3 }
, { name: 'first', num: 4 }
, { name: 'first', num: 5 }
, { name: 'first', num: 6 }
, { name: 'first', num: 7 }
, { name: 'first', num: 8 }
, { name: 'first', num: 9 }
]
var b = a.filter(el=>!(el.num%2)).map(el=>Object.assign({},el))
// other solution with reduce
var c = a.reduce((acc,cur)=>{
if (!(cur.num%2) )acc.push(Object.assign({},cur))
return acc
}, [])
ConsoleArrayNamNum('var a -1-',a) // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -1-',b) // [2, 4, 6, 8]
ConsoleArrayNamNum('var c -1-',c) // [2, 4, 6, 8]
for(let elm of b)
{ elm.num *= 10 }
ConsoleArrayNamNum('var a -2-',a) // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -2-',b) // [20, 40, 60, 80]
function ConsoleArrayNamNum(title,arr) {
console.log(title)
for(let elm of arr)
{ console.log(`{ name: '${elm.name}', num: ${elm.num} }`) }
}
.as-console-wrapper { min-height: 100% !important; }
If you want a new array with the final values you can use reduce to do it all in one go, reduce starts with an accumulator of an empty array and each iteration if it meets the condition it adds a clone with the spread operator overriding the num time 10.
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
const evensTimes10 = array => array.reduce((results, item) => {
if (item.num % 2 === 0) {
results.push({ ...item, num: item.num * 10 });
}
return results;
}, []);
var b = evensTimes10(a);
console.log('a1',a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b1',b); // [20, 40, 60, 80]
A simple solution using some ES6 syntax:
var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3},
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7},
{name:'first', num: 8}, {name:'first', num: 9}];
const b = a
.filter(el => {
if (el.num % 2 === 0) {
return {
...el
}
}
})
.map(newEl => newEl.num * 10);
console.log('a', a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b', b);
.filter() iterates the "a" array and returns only elements with
"num" property that reaches the condition. This is a cloned array.
return { ...el } returns a cloned object thanks to spread
operator.
.map() creates a new array and returns each "el.num" value *
10
Here some info about .map() .filter() and spread operator:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
I found this very interesting site that lists all Javascript functions with their descriptions and shows if is mutable or not, this helps a lot:
https://doesitmutate.xyz/

Organizing an object to create keys when needed and/or push different attribute to value pair array

The data structure that I am trying to achieve would look as so :
I would like the list_id to become a key in a object, and hold all the id's of the items that have the matching list id.
var lists = { (list_id)1 : [1, 2, 3]
(list_id)2 : [4, 5, 6]
(list_id)3 : [7, 8, 9]
(list_id)4 : [10, 11, 12] };
this object is created from a json data structure that looks like this:
let json = [{ id: 1, list_id: 1 }, { id: 2, list_id: 1 },
{id: 3, list_id: 1 }, {id: 4, list_id: 2 },
{id: 5, list_id: 2 }, {id: 6, list_id: 2 },
{id: 7, list_id: 3 }, {id: 8, list_id: 3 },
{id: 9, list_id: 3 }, {id: 10, list_id: 4 },
{id: 11, list_id: 4 }, {id: 12, list_id: 4 }]
I can make an object that holds all the list_id's as keys but am getting stumped on pushing the actions_id into the value pair array with the matching list id.
let listAll = {};
json.forEach(function(lista, index, listb) {
listAll[lista.list_id] = [];
if ( listAll[lista.list_id] === lista.list_id){
listAll[lista.list_id].push(lista.id)
} else {
listAll[lista.list_id] = [lista.id];
}
});
My goal is to have and object that contains a key for every list_id currently avaliable from the actions.
Then add every action that contains the matching list_id into a value pair array.
the current output of this code is
{ '1': [ 3 ], '2': [ 6 ], '3': [ 9 ], '4': [ 12 ] }
which does not contain all numbers, each array should contain 3 numbers.
An alternative is using the function reduce to group the objects by a specific key = ['list_id', list_id].join('').
let json = [{ id: 1, list_id: 1 }, { id: 2, list_id: 1 }, {id: 3, list_id: 1 }, {id: 4, list_id: 2 }, {id: 5, list_id: 2 }, {id: 6, list_id: 2 }, {id: 7, list_id: 3 }, {id: 8, list_id: 3 }, {id: 9, list_id: 3 }, {id: 10, list_id: 4 }, {id: 11, list_id: 4 }, {id: 12, list_id: 4 }],
result = json.reduce((a, {id, list_id}) => {
let key = ['list_id', list_id].join(''); // For example: this is creating ['list_id', 1] to list_id1
(a[key] || (a[key] = [])).push(id);
return a;
}, Object.create(null)/*This is only to create an object without prototype -> {}*/);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Why don't you try hasOwnProperty instead?
var listAll = {};
json.forEach(function(list, index) {
if (listAll.hasOwnProperty(list.list_id)) {
listAll[list.list_id].push(list.id);
}else {
listAll[list.list_id] = [list.id];
}
});
console.log(listAll);

Need help in getting as much unique beer as possible

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>

Underscore - Compare two arrays of objects (positions)

Is there a way to compare differences between arrays based on changes on their elements positions?
I have an original array of objects which undergoes a change on one of it's element's values, this change is mapped into a new array:
origElements = [{id: 1, value: 50},
{id: 2, value: 60},
{id: 3, value: 70}]
changedElements = [{id: 1, value: 50},
{id: 3, value: 60},
{id: 2, value: 120}]
var diff = _.difference(_.pluck(origElements, "id"), _.pluck(changedElements, "id"));
var result = _.filter(origElements, function(obj) { return diff.indexOf(obj.id) >= 0; });
In this case it is clear why 'result' would return nothing. As there's no difference of values between: [1, 2, 3] and [1, 3, 2]. What I'm trying to achieve here is a 'strict difference' which would look at index as well, thus returning some reference to the new order of the objects.
How about doing it this way:
var origElements = [{
id: 1,
value: 50
}, {
id: 2,
value: 60
}, {
id: 3,
value: 70
}];
var changedElements = [{
id: 1,
value: 50
}, {
id: 3,
value: 60
}, {
id: 2,
value: 120
}];
var origElementsIds = _.pluck(origElements, "id");
var changedElementsIds = _.pluck(changedElements, "id");
console.log("Are array element positions same ?",
origElementsIds.join() === changedElementsIds.join());

Categories

Resources