努力编写代码......迷失在循环中。
我有2个数据集,例如:
var elements = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"345"},
{"id":"21.U2duHWiX.A5q.E0C","amount":"344"}
]
var elements_in_combination = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
]
我正在寻找使用所有元素的最低金额。
答案是329 + 328。
这里有3个元素,例如:
var elements = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"345"},
{"id":"21.U2duHWiX.A5q.E0C","amount":"344"},
{"id":"21.U2duHWiX.P1y.E0C","amount":"343"}
]
var elements_in_combination = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"327","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"327","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"314","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"313","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"312","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]}
]
这里的答案是314 + 313 + 312 ....但我不知道如何使用代码到达那里。
当它们可能不是全部组合在一起时,事情会变得更加复杂,例如:
var elements = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"345"},
{"id":"21.U2duHWiX.A5q.E0C","amount":"344"},
{"id":"21.U2duHWiX.J3e.E0C","amount":"342"},
{"id":"21.U2duHWiX.P1y.E0C","amount":"343"}
]
var elements_in_combination = [
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"326","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"329","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"327","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"326","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"328","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"327","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"326","combination":["21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"327","combination":["21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"314","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"313","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"311","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"314","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"313","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"312","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.A5q.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.0zu.E0C","amount":"314","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"311","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"312","combination":["21.U2duHWiX.0zu.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.A5q.E0C","amount":"313","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.J3e.E0C","amount":"311","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]},
{"id":"21.U2duHWiX.P1y.E0C","amount":"312","combination":["21.U2duHWiX.A5q.E0C","21.U2duHWiX.J3e.E0C","21.U2duHWiX.P1y.E0C"]}
]
有关如何处理此事的任何想法?
(对不起,这很难解释,因为它要解决)
编辑:澄清
这是一个抽象的例子:
var elements = [
{ id: A, value: '#' },
{ id: B, value: '#' },
{ id: C, value: '#' }
]
var elements_in_combination = [
{ id: A, value: '#', combinations: [A, B] },
{ id: B, value: '#', combinations: [A, B] },
{ id: A, value: '#', combinations: [A, C] },
{ id: C, value: '#', combinations: [A, C] },
{ id: B, value: '#', combinations: [B, C] },
{ id: C, value: '#', combinations: [B, C] },
{ id: A, value: '#', combinations: [A, B, C] },
{ id: B, value: '#', combinations: [A, B, C] },
{ id: C, value: '#', combinations: [A, B, C] },
]
我想知道产生最低值的是什么,计算是:
[A, B, C] = '##'
or
[A, B] + C = '##'
or
[A, C] + B = '##'
or
A + [B, C] = '##'
or
A + B + C = '##'
然后我需要从元素和具有最佳组合的elements_in_combination构建一个数组,例如:
var elements = [
{ id: A, value: '#', combinations: [A, B] },
{ id: B, value: '#', combinations: [A, B] },
{ id: C, value: '#' }
]
答案 0 :(得分:1)
行。检查此脚本:
// this part is only needed if your ids are arbitrary, and can contain the join-character
// if not, you could replace this by the identity function
var count = 0, numericids = {};
function getNumericId(id) {
return id in numericids ? numericids[id] : numericids[id] = count++;
}
// returns the same (reversible) id for all similiar [unsorted] key combinations
function id(keys) {
return keys.map(getNumericId).sort().join('-');
// you might remove the getNumericId part if distinct without
}
// now, build a map that holds the summed amount for each single (sub)combination
var amounts = {};
function add(amount, keys) {
var key = id (keys);
if (key in amounts)
amounts[key] += amount;
else
amounts[key] = amount;
}
for (var i=0; i<elements.length; i++) // each element is a single combination
add(Number(elements[i].amount), [elements[i].id]);
for (var i=0; i<elements_in_combination.length; i++)
add(Number(elements_in_combination[i].amount), elements_in_combination[i].combination);
// so we have the amounts in a good accessible structure now
接下来,我们需要找到所有partitions of a set。哇。这是一个NP难问题,不容易解决。三个元素(你的问题中的五个组合)容易变得越来越复杂,对于6个元素你已经有203种可能性(Bell numbers。为了进一步阅读,我找到了
好的,让我们递归地解决这个问题,缓存结果并获得最小值:
// first, get the set for which we want to determine the result:
var initialset = elements.map(function(el){return getNumericId(el.id);}).sort();
// set up a cache for minimum value results:
var cache = {};
function partition(set) {
// returns an array of all partitionings into two parts
var results = [[[set[0]],[]]];
for (var i=1; i<set.length; i++)
for (var j=0, l=results.length; j<l; j++) {
// repeat the array with duplicates
results[j+l] = [results[j][0].slice(),results[j][1].slice()];
// but while we push to the first part in the first half
results[ j ][0].push(set[i]);
// we push to the second part in the second half
results[j+l][1].push(set[i]);
}
return results;
}
function getMin(set) {
var key = set.join('-');
if (key in cache) // quick escape
return cache[key];
var result = {amount:Infinity, set:null};
if (key in amounts) // there is a combination with this
result = {amount:amounts[key], set:[key]};
var divisions = partition(set);
// for all possibilities to divide the set in two parts
// (unless the first, which is [set, []])
for (var i=1; i<divisions.length; i++) {
// get the minimal amounts of both parts
var first = getMin(divisions[i][0]);
var second = getMin(divisions[i][1]);
var sum = first.amount + second.amount;
if (sum < result.amount) // and find new minima
result = {amount:sum, set: first.set.concat(second.set)};
}
return cache[key] = result;
}
// And now invoke this monster!
if (!initialset.length) throw new Error("When searching for nothing you would find nothing");
var min = getMin(initialset);
cache = null, amounts = null; // and immediately free the memory
所以,这是你的结果!它包含amount
属性中所需的总和以及set
属性中使用的组合键集。
现在可以轻松构建元素数组:
var elemArr = [];
function addElem(el, comb) {
if (min.set.indexOf(id(comb)) >= 0)
elemArr.push(el);
}
for (var i=0; i<elements.length; i++) // each element is a single combination
addElem(elements[i], [elements[i].id]);
for (var i=0; i<elements_in_combination.length; i++)
addElem(elements_in_combination[i], elements_in_combination[i].combination);
return elemArr; // We've done it!
该脚本会为您的所有示例返回正确的结果:
请注意,这些可能不是唯一的解决方案,因为只有许多可能的最小值中的第一个
答案 1 :(得分:0)
function find_matches(elements, elements_in_combination) {
var matches = ();
var element_ids = ();
for (var i = 0; i < elements.length; i++) {
element_ids.push(elements[i].id);
}
element_ids.sort();
for (i = 0; i < elements_in_combination.length; i++) {
combs = elements_in_combination[i].combination.slice(0).sort();
if (array_equal(element_ids, combs)) {
matches.push(elements_in_combination[i].amount;
}
}
return matches;
}
有关如何实施array_equal()
的信息,请参见this question。
答案 2 :(得分:0)
好吧..这可能是一个选项,但因为我不知道“最佳组合”的条款是什么,我无法进一步减少它。
以下代码应该生成一个包含每个元素作为对象的对象。然后,每个元素对象将包含每个唯一量的另一个对象(从低到高)。然后,金额对象包含该金额可能的组合。
即。容器对象( finalElements ) - 元素id - order&amp;金额 - 组合:
var finalElements = { };
// sort:
elements_in_combination.sort( eic_sortOnAmmount );
function eic_sortOnAmmount( a, b ) {
return a.amount - b.amount;
}
// parse the elements array and create an object for each element
// add the initial amount as a key:
for( var i in elements ) {
finalElements[ elements[i].id ] = { order:[] };
finalElements[ elements[i].id ][ elements[ i ].amount ] = null;
}
// parse the elements_in_combination array
// if the id matches one of the elements in finalElements
// add its amount and combination
for( var i in elements_in_combination ) {
if( finalElements.hasOwnProperty( elements_in_combination[ i ].id ) ) {
if( finalElements[ elements_in_combination[ i ].id ].hasOwnProperty( elements_in_combination[ i ].amount ) ) {
finalElements[ elements_in_combination[ i ].id ][ elements_in_combination[ i ].amount ].push( elements_in_combination[ i ].combination );
} else {
finalElements[ elements_in_combination[ i ].id ].order.push(elements_in_combination[ i ].amount);
finalElements[ elements_in_combination[ i ].id ][ elements_in_combination[ i ].amount] = [ elements_in_combination[ i ].combination ];
}
}
}
示例用法:
console.log(finalElements["21.U2duHWiX.0zu.E0C"].order[0]); //produces 314
console.log(finalElements["21.U2duHWiX.0zu.E0C"][finalElements["21.U2duHWiX.0zu.E0C"].order[0]]); // produces the combinations for 314
希望这有帮助 - 顺便说一下:空金额是原始元素金额。