Combinando matrices para casos de uso.

Aplicación Node.js, escribiendo pruebas de validación. Dado lo siguiente:

var obj = { foo: null, bar: null, baz: null}, values = [ 0, 1]; 

Necesito crear un número n de objetos para tener en cuenta cada propiedad que tiene asignada cada combinación de valores posibles, para representar cada caso de uso posible. Entonces, para este ejemplo, la salida debe ser 2 ^ 3 = 8 objetos, por ejemplo

 [ { foo: 0, bar: 0, baz: 0}, { foo: 0, bar: 1, baz: 0}, { foo: 0, bar: 1, baz: 1}, { foo: 0, bar: 0, baz: 1}, { foo: 1, bar: 0, baz: 0}, { foo: 1, bar: 1, baz: 0}, { foo: 1, bar: 1, baz: 1}, { foo: 1, bar: 0, baz: 1}, ] 

El subrayado o el lodash u otras bibliotecas son soluciones aceptables. Idealmente, me gustaría algo así:

 var mapUseCases = function(current, remaining) { // using Underscore, for example, pull the current case out of the // possible cases, perform logic, then continue iterating through // remaining cases var result = current.map(function(item) { // perform some kind of logic, idk return magic(item); }); return mapUseCases(result, _.without(remaining, current)); } var myValidationHeadache = mapUseCases(currentThing, somethingElse); 

Perdone mi pseudocódigo, creo que me rompí el cerebro. ¯ \ _ (ツ) _ / ¯

Solución para cualquier longitud de objeto y cualquier valor.

Tenga en cuenta que los valores no undefined no aparecen.

 function buildObjects(o) { var keys = Object.keys(o), result = []; function x(p, tupel) { o[keys[p]].forEach(function (a) { if (p + 1 < keys.length) { x(p + 1, tupel.concat(a)); } else { result.push(tupel.concat(a).reduce(function (r, b, i) { r[keys[i]] = b; return r; }, {})); } }); } x(0, []); return result; } document.write('
' + JSON.stringify(buildObjects({ foo: [0, 1, 2], bar: [true, false], baz: [true, false, 0, 1, 42] }), 0, 4) + '

');

Una forma es contar desde “000” hasta “999” en un sistema values.length :

 keys = ['foo','bar','baz'] values = ['A', 'B'] width = keys.length base = values.length out = [] for(var i = 0; i < Math.pow(base, width); i++) { var d = [], j = i; while(d.length < width) { d.unshift(j % base) j = Math.floor(j / base) } var p = {}; for(var k = 0; k < width; k++) p[keys[k]] = values[d[k]] out.push(p) } document.write('
'+JSON.stringify(out,0,3))

Esta es una versión non-recursive de lo que quieres:

 function createRange(keys, values) { if (typeof values[0] !== typeof []) values = keys.map(k => values); var pointer = {}; var repeats = 1; keys.forEach((k, i) => { var vLen = values[i].length; repeats *= vLen; pointer[k] = { get value() { return values[i][pointer[k].current] }, current: 0, period: Math.pow(vLen, i), inc: function() { var ptr = pointer[k]; ptr.current++; if (ptr.current < vLen) return; ptr.current = 0; if (i + 1 === keys.length) return; var nk = keys[i + 1]; pointer[nk].inc() } }; }); var result = []; for (var i = 0; i < repeats; i++) { var o = {}; result.push(o); keys.forEach(k => o[k] = pointer[k].value) pointer[keys[0]].inc(); } return result; } var objKeys = ['u', 'v', 'w', 'x', 'y', 'z']; var objValues = [ ['1', '2', '3'], ['a', 'b', 'c'], ['foo', 'bar', 'baz'], [1, 3, 2], ['test', 'try', 'catch'], ['Hello', 'World'], ]; var range = createRange(objKeys, objValues); range.map(v => document.write(JSON.stringify(v).big()))