2012-02-13 9 views
16

Ho due matrici:Combinando due matrici per formare un oggetto JavaScript

var columns = ["Date", "Number", "Size", "Location", "Age"]; 

var rows = [["2001", "5", "Big", "Sydney", "25"],["2005", "2", "Med", "Melbourne", "50"],["2012", "20", "Huge", "Brisbane", "80"]]; 

sto cercando di combinare in un oggetto JavaScript per ogni elemento dell'array righe. Dopodiché, voglio spingere ogni oggetto in un nuovo array.

come:

var newarray = []; 

//'thing' should be the same structure for each row item 
var thing = { 
    "Date" : "2001", 
    "Number" : "5", 
    "Size":"Big", 
    "Location":"Sydney", 
    "Age":"25" 
} 

newarray.push(thing); 

posso fare questo quando so i nomi delle colonne, ma ho bisogno di essere in grado di memorizzare i dati in questo modo, quando il nome di colonna è sconosciuto - vale a dire sulla base del indici dell'array di colonne.

ho provato come questo prima:

 for(var y = 0; y < rows.length; y++){ 

      for(var i = 0; i < columns.length; i++){ 
       thing[columns[i]] = rows[i][i]; 
      } 
       newarray.push(thing) 
     } 

Il codice sopra unico memorizzato il primo elemento ripetutamente (secondo rows.length).

Non capisco come combinare i nomi delle colonne con le righe per creare una matrice di oggetti. Il fatto che le "righe" contengano array è particolarmente confuso.

risposta

9

Creare un nuovo thing oggetto all'inizio di ogni iterazione del ciclo esterno. Se non lo fai, ogni volta che pronunci lo thing[columns[i]] sovrascrivi le proprietà dello stesso oggetto e quando lo inserisci in newarray, quello che ti ritrovi è un array pieno di riferimenti allo lo stesso oggetto. Inoltre, all'interno del ciclo di essere sicuri di ottenere gli indici a destra (avete attualmente ottenuto [i][i] invece di [y][i]):

var newarray = [], 
    thing; 

for(var y = 0; y < rows.length; y++){ 
    thing = {}; 
    for(var i = 0; i < columns.length; i++){ 
     thing[columns[i]] = rows[y][i]; 
    } 
    newarray.push(thing) 
} 

"Il fatto che 'le righe' contiene array è particolarmente confusa .."

Per i vostri dati di esempio rows.length saranno 3, e rows[0] è la matrice:

["2001", "5", "Big", "Sydney", "25"] 

rows[0][3] è "Sydney".

Usando questo come esempio dovresti essere in grado di vedere cosa rows[y][i] ti darà per ogni valore di y e i ...

1

È necessario specificare la riga corretta. Stai usando la colonna Sostituire rows[i][i] con rows[y][i]. Inoltre, sembra che tu stia riutilizzando lo stesso oggetto thing più e più volte. Invece dovresti definirlo di nuovo ogni iterazione attraverso l'array (var thing = {};).

var newarray = []; 
    for (var y = 0; y < rows.length; y++) { 
     var thing = {}; 
     for (var i = 0; i < columns.length; i++) { 
      thing[columns[i]] = rows[y][i]; 
     } 
     newarray.push(thing); 
    } 
+0

Grazie, ho provato in questo modo, e sto avendo lo stesso problema. Vedi: [JSFiddle] (http://jsfiddle.net/tamarasaurus/V42Hx/). Mi sto perdendo qualcosa? – tamarasaurus

+0

@tamarasaurus, hai visto il mio ultimo aggiornamento? Ho aggiunto una parte che specifica che è necessario impostare 'var thing = []' ogni iterazione del ciclo. Il tuo JSFiddle non lo mostra. –

+0

Vedere http://jsfiddle.net/V42Hx/2/ con la modifica aggiunta. Sembra funzionare. –

0

si solo bisogno di resettare thing

for(var y = 0; y < rows.length; y++){ 
    for(var i = 0; i < columns.length; i++){ 
     thing[columns[i]] = rows[y][i]; 
    } 

    newarray.push(thing); 
    thing = {};  
} 

vedi aggiornamento: fiddle

19

Si potrebbe anche fare questo in maniera più data-centric:

var columns = ["Date", "Number", "Size", "Location", "Age"]; 

var rows = [ 
    ["2001", "5", "Big", "Sydney", "25"], 
    ["2005", "2", "Med", "Melbourne", "50"], 
    ["2012", "20", "Huge", "Brisbane", "80"] 
]; 

var result = rows.map(function(row) { 
    return row.reduce(function(result, field, index) { 
    result[columns[index]] = field; 
    return result; 
    }, {}); 
}); 

In questo modo non dovrebbe avere a che fare con gli array temporaneo.

Nel caso in cui il codice dovrebbe funzionare su antichi browser così, vi consiglio di dare un'occhiata al underscore.js per l'utilizzo di map + reduce.

4

Nel caso in cui si utilizza Underscore.js c'è _.object(list, [values])

Ed ecco come è implementato:

_.object = function(list, values) { 
    if (list == null) return {}; 
    var result = {}; 
    for (var i = 0, length = list.length; i < length; i++) { 
    if (values) { 
     result[list[i]] = values[i]; 
    } else { 
     result[list[i][0]] = list[i][1]; 
    } 
    } 
    return result; 
}; 
+0

+1. È bello sapere come farlo con puro javascript, ma perché reinventare la ruota? Questa è la migliore soluzione IMHO. È importante sapere/usare underscore o lodash. – Jess

3

Utilizzando funzionale sarebbe come nnnnnn detto, ma con una minore correzione

var columns = ["Date", "Number", "Size", "Location", "Age"]; 

var rows = [ 
    ["2001", "5", "Big", "Sydney", "25"], 
    ["2005", "2", "Med", "Melbourne", "50"], 
    ["2012", "20", "Huge", "Brisbane", "80"] 
]; 

var result = rows.map(function(row) { 
    return row.reduce(function(result, field, index) { 
    result[columns[index]] = field; 
    return result 
    }, {}); 
}); 
0

Invece di eseguire il ciclo su tutta la tabella, è anche possibile utilizzare l'array di colonne per generare una classe Row (utilizzando defineProperty) e quindi utilizzarla classe di riga per avvolgere gli array di righe nell'array di righe. L'array risultante di oggetti Row viene quindi associato all'array delle righe originali, in modo tale che le modifiche in una si riflettano nell'altra. A seconda del tuo caso d'uso, questo potrebbe essere utile o un problema. Un esempio di lavoro è dato nel frammento di seguito.

var columns = ["Date", "Number", "Size", "Location", "Age"]; 
 

 
var rows = [ 
 
    ["2001", "5", "Big", "Sydney", "25"], 
 
    ["2005", "2", "Med", "Melbourne", "50"], 
 
    ["2012", "20", "Huge", "Brisbane", "80"] 
 
]; 
 

 
var table = create_table(columns, rows); 
 

 
// 
 
for (var i = 0; i<table.length; i++) { 
 
    document.writeln("The thing in " + table[i].Location + " is " + table[i].Size + "<br/>"); 
 
} 
 

 
// The rows in table are still tied to those in the rows variable 
 
table[0].Size = "Small"; 
 
document.writeln(JSON.stringify(rows[0])); 
 

 
function create_table(columns, rows) { 
 
    // Create a Row class with the given columns 
 
    for (var i=0; i<columns.length; i++) { 
 
    var c = columns[i]; 
 
    Object.defineProperty(Row.prototype, c, { 
 
     enumerable: true, 
 
     get: getter(i), 
 
     set: setter(i), 
 
    }); 
 
    } 
 
    // Wrap the rows in row objects and return the resulting array 
 
    var r = new Array(rows.length); 
 
    for (var i=0; i<rows.length; i++) { 
 
    r[i] = new Row(rows[i]); 
 
    } 
 
    return r; 
 

 
    function Row(row) { this._ = row; } 
 

 
    // Generators for the getter and setter functions, with variable i stored in a closure. 
 
    function getter(i) { 
 
    return function(){ 
 
     return this._[i]; 
 
    }; 
 
    } 
 
    function setter(i) { 
 
    return function(val){ 
 
     return this._[i] = val; 
 
    }; 
 
    } 
 
}

0

Credo che la mia soluzione è risolvere il tuo problema

codice:

var keys = columns, 
     values = rows, 
     finalarray = []; 

     values.forEach((data,index) =>{ 
      var objJSON = new Object(); 
      for (i = 0; i < keys.length; i++) { 
       objJSON[keys[i]] = data[i]; 
       } 
      finalarray.push(objJSON); 
     }); 

risposta:

console.log(finalarray) 

[{ 
    "Date" : "2001", 
    "Number" : "5", 
    "Size":"Big", 
    "Location":"Sydney", 
    "Age":"25" 
}, 
... 
}] 
0

È possibile utilizzare questa funzione seguente codice ES6:

const assemblyData = (columns, rows) => { 
    return rows.map((row) => { 
     return row.reduce((res, field, index) => { 
     res[columns[index]] = field; 
     return res 
     }, {}); 
    }); 
} 
Problemi correlati