【问题标题】:Combining two arrays to form a javascript object组合两个数组以形成一个 javascript 对象
【发布时间】:2012-03-04 14:28:39
【问题描述】:

我有两个数组:

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

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

我正在尝试将它们组合成一个 javascript 对象,用于 rows 数组中的每个项目。之后,我想将每个对象推入一个新数组中。

喜欢:

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

当我知道列名时我可以这样做,但是当列名未知时我需要能够以这种方式存储数据 - 即基于列数组的索引。

我之前试过这样:

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

上面的代码只是一次又一次地存储了第一项(根据rows.length)。

我不明白如何将列名与行结合起来创建对象数组。 'rows' 包含数组的事实尤其令人困惑..

【问题讨论】:

    标签: javascript arrays object


    【解决方案1】:

    你可以按照 ES6 代码使用这个函数:

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

    Link to examples

    【讨论】:

      【解决方案2】:

      我认为我的解决方案是解决你的问题

      代码:

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

      回答:

      console.log(finalarray)
      
      [{
         "Date" : "2001",
         "Number" : "5",
         "Size":"Big",
         "Location":"Sydney",
         "Age":"25"
      },
      ...
      }]
      

      【讨论】:

        【解决方案3】:

        除了循环整个表之外,您还可以使用列数组生成一个行类(使用defineProperty),然后使用该行类将行数组包装在行数组中。然后将生成的 Row 对象数组绑定到原始 rows 数组,以便其中一个对象的更改反映在另一个对象中。根据您的用例,这可能有用或有问题。下面的 sn-p 给出了一个工作示例。

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

        【讨论】:

          【解决方案4】:

          您也可以以更加以数据为中心的方式来做到这一点:

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

          这样您就不必处理临时数组了。

          如果您的代码也适用于古代浏览器,我建议您查看underscore.js 以使用map + reduce

          【讨论】:

          【解决方案5】:

          如果您使用的是 Underscore.js,则有 _.object(list, [values])

          下面是它的实现方式:

          _.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;
          };
          

          【讨论】:

          • +1。很高兴知道如何使用纯 JavaScript 做到这一点,但为什么要重新发明轮子呢?这是最好的解决方案恕我直言。了解/使用下划线或 lodash 很重要。
          【解决方案6】:

          使用函数就像 nnnnnn 说的,但有一个小的更正

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

          【讨论】:

            【解决方案7】:

            在外循环的每次迭代开始时创建一个新的thing 对象。如果你不这样做,每次你说thing[columns[i]]你都会覆盖同一个对象的属性,当你把它推入newarray时,你最终会得到一个充满引用的数组同一个对象。另外,在循环内确保你得到正确的索引(你目前得到的是[i][i]而不是[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)
            }
            

            “'rows' 包含数组的事实尤其令人困惑..”

            对于您的示例数据,rows.length 将是 3,rows[0] 是数组:

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

            rows[0][3] 是“悉尼”。

            以此为例,您应该能够看到rows[y][i] 将为yi 的每个值提供什么...

            【讨论】:

              【解决方案8】:

              您需要指定正确的行。您正在使用该列。将rows[i][i] 替换为rows[y][i]。此外,看起来您一遍又一遍地重复使用相同的 thing 对象。相反,您应该在数组的每次迭代中重新定义它 (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);
                 }
              

              【讨论】:

              • 谢谢,我试过了,我也遇到了同样的问题。请参阅:JSFiddle。我错过了什么吗?
              • @tamarasaurus,你看到我的最新更新了吗?我添加了一个部分,指定您需要在循环的每次迭代中设置var thing = []。你的 JSFiddle 没有显示出来。
              • @BenLee, thing 是一个对象,而不是一个数组
              • @epoch,你是对的,这是一个错字。更新了我的答案,每次都创建一个新的 object(只使用{} 而不是[])。还有 JSFiddle:jsfiddle.net/V42Hx/3
              【解决方案9】:

              你只需要重置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 = {};    
               }
              

              查看更新:fiddle

              【讨论】:

                猜你喜欢
                • 2016-11-12
                • 2022-01-04
                • 2018-11-17
                • 2019-10-25
                • 2017-02-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多