如何将元素插入到javascript中二维数组的特定索引中?

How to insert elements into specific index in a 2D array in javascript?

我有一个如下所示的对象

const tableData = [
    {
        
        "Location": "London",
        "Status": "Unknown"
    },
    {
        
        "Location": "Delhi",
        "Status": "Reachable"
    },
    {
        
        "Location": "Berlin",
        "Status": "Unknown"
    },
    {
        
        "Location": "Tokyo",
        "Status": "Busy"
    },
]

现在我想创建一个二维数组,它将以某种方式保存这些信息。下面是我的代码

const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = Array(Object.keys(statusOrder).length).fill([]);
for(let i=0; i< tableData.length; i++) {
    const status = tableData[i]["Status"].trim()
    const statusIndex = statusOrder[status]
    statusOrderInfo[statusIndex].push(tableData[i])
}
console.log(statusOrderInfo)

如您所见,我希望 tableData 对象的每个项目都位于二维数组的某个索引中。因此,包含 StatusReachable 的项目应该位于索引 0,包含 StatusBusy 的项目应该位于索引 1,依此类推。

所以最终的输出应该是这样的

[
   [
      {
         "Location":"Delhi",
         "Status":"Reachable"
      }
   ],
   [
      {
         "Location":"Tokyo",
         "Status":"Busy"
      }
   ],
   [
      {
         "Location":"London",
         "Status":"Unknown"
      },
      {
         "Location":"Berlin",
         "Status":"Unknown"
      }
   ]
]

但是我在 运行 上面的代码中得到了错误的输出,即使我的目标是正确的索引。我的方法有什么问题?

使用Array#reduce:

const 
  tableData = [ { "Location": "London", "Status": "Unknown" }, { "Location": "Delhi", "Status": "Reachable" }, { "Location": "Berlin", "Status": "Unknown" }, { "Location": "Tokyo", "Status": "Busy" } ],
  statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2};

const statusOrderInfo = tableData.reduce((list, e) => {
  const index = statusOrder[e.Status];
  list[index] = [...(list[index] || []), {...e}];
  return list;
}, []);

console.log(statusOrderInfo);

解决你的问题的简单方法是改变你的方式来设置 statusOrderInfo 的初始值并使用 Array.from 而不是 Array.fill 像这样:

let statusOrderInfo = Array.from({length: Object.keys(statusOrder).length}, ()=> []);

另一个解决方案是用空数组设置statusOrderInfo的初始值,然后在你的for循环中,根据status值得到当前对象的索引后,你可以检查是否statusIndex是否已经存在于statusOrderInfo中,像这样:

const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
let statusOrderInfo = [];
for(let i=0; i< tableData.length; i++) {
    const status = tableData[i]["Status"].trim()
    const statusIndex = statusOrder[status];
    if(statusOrderInfo[statusIndex]) statusOrderInfo[statusIndex].push(tableData[i]);
    else statusOrderInfo[statusIndex] = [ tableData[i] ]
}
console.log(statusOrderInfo);

另一种解决方案,是在数组上使用 reduce 方法,如下所示:

const tableData = [{

    "Location": "London",
    "Status": "Unknown"
  },
  {

    "Location": "Delhi",
    "Status": "Reachable"
  },
  {

    "Location": "Berlin",
    "Status": "Unknown"
  },
  {

    "Location": "Tokyo",
    "Status": "Busy"
  },
];
const statusOrder = {"Reachable": 0, "Busy": 1, "Unknown": 2}
const result = tableData.reduce((acc, cur) => {
  const index = statusOrder[cur.Status];
  if (acc[index]) acc[index].push(cur);
  else acc[index] = [cur]
  return acc;
}, []);
console.log(result)

另一种声明方式的解决方案:

首先使用 Array#sort

按状态代码对对象进行排序

然后使用 Array#map

将每个对象包装到它自己的数组中

const tableData = [{Location: "London",Status: "Unknown"},{Location: "Delhi",Status: "Reachable"},{Location: "Berlin",Status: "Unknown"},{Location: "Tokyo",Status: "Busy"}]
const statusOrder = {Reachable: 0, Busy: 1, Unknown: 2}

const result = tableData
  .sort(({ Status: s1 }, { Status: s2 }) => statusOrder[s1] - statusOrder[s2])
  .map((item) => [item]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

正如其他人所解释的那样,reduce 将是您的方案的最佳选择。因为在每次迭代中你都会创建一个新的 Array 对象。

const tableData = [{ Location: "London", Status: "Unknown" }, { Location: "Delhi", Status: "Reachable" }, { Location: "Berlin", Status: "Unknown" }, { Location: "Tokyo", Status: "Busy" }]
const statusOrder = { "Reachable": 0, "Busy": 1, "Unknown": 2 };

const statusOrderInfo = tableData.reduce((accumulator, currentValue) => {
  const index = statusOrder[currentValue.Status];
  if (accumulator[index]) {
    accumulator[index].push(currentValue);
  } else {
    accumulator[index] = [currentValue];
  }
  return accumulator;
}, []);

console.log(statusOrderInfo);

对代码中发生的事情的解释:

因为您已经使用 [].fill([]) 来填充数组。它只会创建一个空的 Array 对象并用它来初始化实际的数组。这就是为什么下面的代码片段表现得像它应该表现的那样:)

const statusOrderInfo = Array(3).fill([]);
statusOrderInfo[0].push(10);

console.log(statusOrderInfo);
/* Results:
[
  [ 10 ],
  [ 10 ],
  [ 10 ]
]
*/

这是我的解决方案:

let statuses = ["Reachable", "Busy", "Unknown"];
const tableData = [
    {"Location": "London", "Status": "Unknown"},
    {"Location": "Delhi", "Status": "Reachable" },
    {"Location": "Berlin", "Status": "Unknown"},
    {"Location": "Tokyo", "Status": "Busy"}
];

let result = statuses.map(status => tableData.filter(tableDataItem => tableDataItem.Status == status));
console.log(result);