如何从二维数组中提取多列?

Posted

技术标签:

【中文标题】如何从二维数组中提取多列?【英文标题】:How to extract multiple columns from a two dimension array? 【发布时间】:2020-12-13 02:37:03 【问题描述】:

我能否就如何使用 javascript 从如下所示的二维数组中提取多列有一些指导?

Array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];

到目前为止,我看到的使用 forEach 或 map 的简单方法将允许一次提取一列,有没有办法以某种方式嵌套它以提取一个想要的列索引?

假设欲望输出列是 1,2 和 4。

Output = [
  [1, 2, 4],
  [5, 6, 8],
  [9,10,12],
];

编辑:

我需要解决的另一个问题是如果一行是 Array[i][1]=0 或为空,如何删除它。

假设我们有额外的数组元素...

Array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [17, ,19,20],
  [21,22,23,24],
]; 

现在想要的输出是……

Output = [
  [1, 2, 4],
  [5, 6, 8],
  [9,10,12],
  [21,22,24],
]; 

【问题讨论】:

我不知道你想要什么,你能添加你想要的输出吗? 您能否展示您想要的输出示例以及如何指定要提取的列? 这将有助于显示您已经尝试过的内容和所需的输出,以及建议的函数定义(如果您已经获得的话)。 您可以使用索引参数,例如 . array.map(elem,index,array) 【参考方案1】:

您可以将arr 中的每一行.map() 转换为一个新数组,您可以通过在您希望获得的列/索引数组上使用内部.map() 来获得该数组。内部映射会将每个索引映射到行中的关联值,为您提供每行每列的值。

请看下面的例子:

const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];

const cols = [1, 2, 4];
const res = arr.map(r => cols.map(i => r[i-1]));
console.log(res);

更多详情: 正如您所提到的,第一个映射将 arr 内部的每个内部数组暴露给内部映射函数:

cols.map(i => r[i-1])

此映射函数将遍历cols 内部定义的索引并将它们转换为新值。比如说你是r是第二个数组:

[5, 6, 7, 8]

执行cols.map(...) 将遍历[1, 2, 4] 中的每个元素(在回调函数中由i 表示)。对于每个元素,我们将其“转换”为一个新元素:

i = 1
r = [5, 6, 7, 8]
new value: r[1-1] = 5

下一次迭代我们查看cols中的下一个值:

i = 2
r = [5, 6, 7, 8]
new value: r[2-1] = 6

最后,我们看看cols中的最终值:

i = 4
r = [5, 6, 7, 8]
new value: r[4-1] = 8

因此,映射函数会生成一个新数组,该数组将 cols [1, 2, 4] 中的值转换为当前行中这些索引处的值 [5, 6, 8]。这发生在每个内部数组/行上,产生最终结果。


编辑 根据您的编辑,您可以从上面应用相同的逻辑来获取仅包含所需列的数组。完成后,您可以使用.filter() 仅保留第二列中具有truthy 值的行。在第二列中保留所有具有真实值的数组将从结果数组中删除第二列中具有非真实值的数组(falsy 值)。 0undefined 都是不稳定的值,因此不会保留它们。

请看下面的例子:

const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [17, ,19,20],
  [21,22,23,24],
]

const cols = [1, 2, 4];
const col = 2;
const res = arr.filter(r => r[col-1]).map(r => cols.map(i => r[i-1]));
console.log(res);

如果您有多个要忽略的列,您可以使用.every() 来确保每个(即:每个)列都包含一个真实值。如果他们都这样做,那么.every() 将返回true,保留该列,否则,它将返回false,删除该列:

const arr = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
  [13,0,15,16],
  [ ,17,19,20],
  [21,22,23,24],
]

const cols = [1, 2, 4];
const col = [1, 2];
const res = arr.filter(r => col.every(c => r[c-1])).map(r => cols.map(i => r[i-1]));
console.log(res);

【讨论】:

工作愉快!第一个映射将 arr 中的每个元素暴露给 (r => cols.map(i => r[i-1]))。但确切地说,这些括号内发生了什么......有点超出我的能力,你能帮忙详细说明一下,以便我们更好地了解它是如何工作的吗? @user1488934 当然,我尝试添加更多细节。简而言之,内部.map()cols 获取值并将它们视为索引。所以对于当前数组r,它会将cols中的每个索引值i映射到r中该索引处的值 @Nick_Parsons,如果我们现在需要过滤第 1 列和第 2 列;常量 col = [1,2]; ,我们该如何实现呢?我试过 const res = arr.map(r => cols.map(i => r[i-1])).filter(r => r[col.map(i => r[i-1] )-1]);也适用于具有 30 列和 5000 多行的大型数据集;在 map 之前过滤会更有益于性能吗? 我已经更新了我的答案(参见最后一个隐藏代码 sn-p)。它的性能为 N*M + N*K,其中 N = arr 的大小,M = cols 的大小,K = col 的大小。如果您先进行过滤,则性能将是 N*K + X*M,其中 X = 过滤后数组的大小。在最坏的情况下,过滤器不会从您的arr 中删除任何元素,在这种情况下 X = N。所以,你是对的。在地图之前执行过滤器会更高效,因为X 通常会小于N,使得 N*K + X*M 【参考方案2】:

您可以按照以下给定的方式处理它。解决方法是使用 filter 方法中可用的 index 参数。

Array.filter(currElem,index,array)

由于数组是 0-indexed ,所以我创建了您想要在数据中作为 [0,1,3] 的索引的数组。您需要将数据数组和索引数组传递给函数。

var array = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12],
];

var arrIndex = [0,1,3];

function extractData(arr,indexArr) 

  return arr.map(obj =>   
      return obj.filter((ob,index) => 
          if(indexArr.includes(index))return ob
      )
  )


console.log(extractData(array,arrIndex));

【讨论】:

以上是关于如何从二维数组中提取多列?的主要内容,如果未能解决你的问题,请参考以下文章

如何从二维数组中获取第一列的内容

从列表中提取二维数组的 Pythonic 方法

listbox的值怎么获取vba

提取二维数组中最小点的索引

vba 赋值给二维数组?

有没有办法在二维数组中提取连续特征