组合两个数组形成一个 JavaScript 对象

问题描述 投票:0回答:12

我有两个数组:

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

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

javascript arrays object
12个回答
34
投票

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

const columns = ["Date", "Number", "Size", "Location", "Age"]

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

const result = rows.map(row =>
  row.reduce(
    (result, field, index) => ({ ...result, [columns[index]]: field }),
    {}
  )
)

console.log(result)

2022 年更新:使用现在更常见的语法(短函数)

这是原始片段:

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

console.log(result)

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

如果您的代码也可以在 ancient 浏览器上运行,我建议您查看 lodash 以使用

map
+
reduce


16
投票

在外循环每次迭代开始时创建一个新的

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.length
将为3,
rows[0]
是数组:

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

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

以此为例,您应该能够看到

rows[y][i]
将为您提供
y
i
的每个值...


4
投票

如果您使用的是 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;
};

3
投票

使用函数就像 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
  }, {});
});

1
投票

您需要指定正确的行。您正在使用该色谱柱。将

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

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

示例链接


1
投票

使用现代 JS,您可以使用

Object.fromEntries()
为您构建对象:

const columns = ["Date", "Number", "Size", "Location", "Age"];
const rows = [["2001", "5", "Big", "Sydney", "25"],["2005", "2", "Med", "Melbourne", "50"],["2012", "20", "Huge", "Brisbane", "80"]];

const res = rows.map(row => Object.fromEntries(
  columns.map((key, i) => [key, row[i]]))
);
console.log(res);

在上面,我正在为

[[key1, value1], [key2, value2], ...]
中的每个 .map()
 构建一个 
row
形式的数组,其中
rows
 ,并将其传递到 
Object.fromEntries()
调用中,该调用为我们构建一个对象形式为
{key1: value1, key2: value2}
.

的键值对数组

1
投票

您可以将 Array.prototype.map()Object.fromEntries()

结合使用

代码:

const columns = ["Date", "Number", "Size", "Location", "Age"];
const rows = [["2001", "5", "Big", "Sydney", "25"],["2005", "2", "Med", "Melbourne", "50"],["2012", "20", "Huge", "Brisbane", "80"]]

const result = rows.map(r => Object.fromEntries(r.map((c, i) => [columns[i], c])))

console.log(result)


0
投票

您只需重置

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

查看更新:小提琴


0
投票

我认为我的解决方案可以解决您的问题

代码:

    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"
},
...
}]

0
投票

const columns = ["Date", "Number", "Size", "Location", "Age"]
const rows = [
  ["2001", "5", "Big", "Sydney", "25"],
  ["2005", "2", "Med", "Melbourne", "50"]
]

const a = Array.from(rows, r => Object.fromEntries(
  Array.from(r, (v, i) => [columns[i], v])
));
console.log(a)


-1
投票

您还可以使用 columns 数组生成 Row 类(使用 defineProperty),然后使用该 row 类将行数组包装在 rows 数组中,而不是循环遍历整个表。然后,生成的 Row 对象数组将与原始 rows 数组绑定,这样一个数组中的更改就会反映在另一个数组中。根据您的用例,这可能有用也可能有问题。下面的代码片段给出了一个工作示例。

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

© www.soinside.com 2019 - 2024. All rights reserved.