2013-09-23 24 views
6

Devo generare un set completo di varianti basato su un elenco di attributi N, mantenendo intatto il nome dell'attributo.Prodotto cartesiano di oggetti in javascript

var input = [ 
    { 'colour' : ['red', 'green'] }, 
    { 'material' : ['cotton', 'wool', 'silk'] }, 
    { 'shape' : ['round', 'square', 'rectangle'] } 
]; 

var expected = [ 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'cotton', 'shape': 'rectangle' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'wool', 'shape': 'rectangle' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'round' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'square' }, 
    { 'colour': 'red', 'material': 'silk', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'cotton', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'wool', 'shape': 'rectangle' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'round' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'square' }, 
    { 'colour': 'green', 'material': 'silk', 'shape': 'rectangle' } 
]; 

Ci sono un sacco di algoritmi in giro per i prodotti cartesiani di array, ma io non riesco a trovare uno per gli oggetti che conserva le chiavi.

Le prestazioni non sono un problema enorme poiché non ci saranno mai più di una dozzina di valori per ogni attributo. L'ordine non deve corrispondere esattamente a expected.

Ho fatto un primo tentativo sulla base di algoritmi standard per le liste, ma sto lottando:

function cartesianProduct(input, current) { 
    if (!input || input.length < 1) { 
     return []; 
    } 

    var head = input[0]; 
    var tail = input.slice(1); 
    var output = []; 

    for (var key in head) { 
     for (var i = 0; i < head[key].length; i++) { 
      if (typeof current == 'undefined') { 
       var current = {}; 
      } 

      current[key] = head[key][i]; 
      var productOfTail = cartesianProduct(tail, current); 
      output.push(current); 
      console.log(current); 
     } 
    } 

    return output; 
} 

console.log(cartesianProduct(input)); 
+0

[Una domanda simile è stata posta qui] (http://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in -javascript) – Keithamus

+0

c'è un grosso problema nel tuo codice: non lo dichiari come var, quindi è considerato una var globale, quindi cambia d nella funzione interna chiama ... – GameAlchemist

risposta

4

Una volta si sbarazzarsi del ' 'i' è un problema globale var', è può arrivare al risultato con questo codice per esempio:

var input = [ 
    { 'colour' : ['red', 'green'] }, 
    { 'material' : ['cotton', 'wool', 'silk'] }, 
    { 'shape' : ['round', 'square', 'rectangle'] } 
]; 

function cartesianProduct(input, current) { 
    if (!input || !input.length) { return []; } 

    var head = input[0]; 
    var tail = input.slice(1); 
    var output = []; 

    for (var key in head) { 
     for (var i = 0; i < head[key].length; i++) { 
      var newCurrent = copy(current);   
      newCurrent[key] = head[key][i]; 
      if (tail.length) { 
       var productOfTail = 
         cartesianProduct(tail, newCurrent); 
       output = output.concat(productOfTail); 
      } else output.push(newCurrent); 
     } 
    }  
    return output; 
} 

function copy(obj) { 
    var res = {}; 
    for (var p in obj) res[p] = obj[p]; 
    return res; 
} 


console.log(cartesianProduct(input)); 
+0

Cheers, per quello, sapevo che c'era un problema con la spinta corrente alla matrice di output, ma non riuscivo a capire perché. –

+0

Prego. Come hai già capito, senza copiare, continui a cambiare un singolo oggetto in ogni chiamata ricorsiva, quindi il prodotto non funziona. – GameAlchemist

Problemi correlati