2012-02-13 9 views
16

Mam dwie tablice:Łącząc dwie tablice w celu utworzenia JavaScript Object

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

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

Próbuję połączyć je w javascript obiektu dla każdego elementu w tablicy wiersze. Następnie chcę przenieść każdy obiekt do nowej tablicy.

odczuwalna:

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); 

mogę to zrobić, gdy wiem, nazwy kolumn, ale muszę być w stanie przechowywać dane w ten sposób, gdy nazwa kolumna jest nieznany - czyli w oparciu o indeksy tablicy kolumn.

próbowałem go tak przed:

 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) 
     } 

powyższy kod przechowywane tylko pierwszego elementu znowu i znowu (według rows.length).

Nie rozumiem, jak łączyć nazwy kolumn z wierszami, aby utworzyć tablicę obiektów. Fakt, że "wiersze" zawiera tablice, jest szczególnie mylący.

Odpowiedz

9

Utwórz nowy thing obiekt na początku każdej iteracji pętli zewnętrznej. Jeśli tego nie zrobisz, za każdym razem, gdy powiesz "thing[columns[i]]", będziesz nadpisywać właściwości tego samego obiektu, a kiedy wciśniesz go do newarray, otrzymasz tablicę pełną odniesień do tego samego obiektu. Również wewnątrz pętli upewnij się dostać indeksy prawo (już obecnie dostał [i][i] zamiast [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) 
} 

„Fakt, że«»zawiera wiersze macierzy jest szczególnie kłopotliwe ..”

Dla danych próbek rows.length będzie 3 i rows[0] jest tablica:

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

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

Używając tego jako przykładu, powinieneś być w stanie zobaczyć, co uzyska rows[y][i] dla każdej wartości y i i ...

1

Musisz podać właściwy wiersz. Używasz kolumny. Wymień rows[i][i] na rows[y][i]. Wygląda na to, że wielokrotnie używasz tego samego obiektu thing. Zamiast tego powinieneś zdefiniować go od nowa w każdej iteracji poprzez tablicę (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

Dzięki, próbowałem to w ten sposób, i mam ten sam problem. Zobacz: [JSFiddle] (http://jsfiddle.net/tamarasaurus/V42Hx/). Czy czegoś brakuje? – tamarasaurus

+0

@amamarasaurus, widziałeś moją ostatnią aktualizację? Dodałem część określającą, że należy ustawić 'var thing = []' w każdej iteracji pętli. Twój JSFiddle tego nie pokazuje. –

+0

Zobacz http://jsfiddle.net/V42Hx/2/ z dodaną zmianą. Wydaje się działać. –

0

wystarczy zresetować 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 = {};  
} 

zobaczyć zmiana: fiddle

19

Można również zrobić to w sposób bardziej zorientowany danych:

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; 
    }, {}); 
}); 

W ten sposób nie będzie musiał radzić sobie z tymczasowymi tablicami.

W przypadku, gdy kod powinien działać na starożytnych przeglądarek jak dobrze, polecam spojrzeć na underscore.js za korzystanie map + reduce.

4

W przypadku korzystania underscore.js jest _.object(list, [values])

A oto jak to jest realizowane:

_.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. Dobrze wiedzieć, jak to zrobić z czystym javascriptem, ale po co wymyślać nowe koło? To najlepsze rozwiązanie IMHO. Ważne jest, aby znać/używać podkreślenia lub lodash. – Jess

3

Korzystanie funkcjonalny będzie jak nnnnnn powiedział, ale z niewielką korektą

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

Zamiast pętli nad całą tabelą, możesz także użyć tablicy kolumn, aby wygenerować klasę wierszy (używając defineProperty), a następnie użyć tej klasa wiersza, aby opakować tablice wierszy w tablicy wierszy. Wynikowa tablica obiektów Row jest następnie powiązana z oryginalną tablicą wierszy, tak że zmiany w jednej są odzwierciedlane w drugiej. W zależności od przypadku użycia może to być przydatne lub stanowić problem. Przykładowy przykład podano w poniższym fragmencie.

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

myślę, że moje rozwiązanie jest rozwiązać problem

Kod:

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); 
     }); 

odpowiedź:

console.log(finalarray) 

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

Można użyć tej funkcji po kodzie ES6:

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