javascript - 如何从更大的二维数组中提取一组孤立的二维数组?
问题描述
假设我有一个 2D 数组,其中填充了很多空白,但在这些空白之间包含较小的独立 2D 数组。例如:
var aVO = [
["col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9"],
["", "", "", "", "", "", "", "", ""],
[1, 2, 3, "", "", "", "", "", ""],
[4, 5, 6, "", "", "a", "b", "", ""],
[7, 8, 9, "", "", "c", "d", "", 1],
["", "", "", "", "", "", "", "", 2],
["", "", "z", "y", "", "", "", "", 3],
["", "x", "w", "v", "", 7, 7, 7, ""],
["", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", ""],
["", "A1", "B1", "", "", "", "", "", ""],
["", "A2", "B2", "C2", "", "", "HELLO", "", ""]
]
我有兴趣将其转换为八个二维数组:
[["col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9"]]
[[1,2,3],[4,5,6],[7,8,9]]
[["a","b"],["c","d"]]
[[1],[2],[3]]
[["", "z","y"],["x","w", "v"]]
[[7,7,7]]
[["A1","B1",""],["A2","B2","C2"]]
[["HELLO"]]
提取这些较小的二维数组的最佳方法是什么?我正在考虑逐行迭代,但很难想象如何优雅地提取数据[["", "z","y"],["x","w","v"]]
(注意“x”如何不在“z”的正下方,因此生成的二维数组需要反映这种转变)。谢谢你的帮助!
解决方案
这是一种使用Set
和Map
实例来跟踪单元组的方法:
- 从二维数组中创建单元格
- 创建一个空
Map
的,我们将为每个单元格存储它所属的组的值 - 循环遍历每个单元格
- 如果单元格为空,则转到下一个单元格
- 如果一个单元格有一个值
- 为它创建一个组。该组标记左上角和右下角位置并跟踪属于它的一组单元格。
- 检查哪些相邻单元格已经属于一个组
- 将新创建的组与为相邻单元格找到的所有组合并
- 从
Map
- 对于每个唯一组,从初始网格中切出其左上角和右下角之间的部分
const Cell = memo(
(r, c) => ({ r, c }),
([r, c]) => `${r}_${c}`
);
Cell.neighbors = ({ r, c }) => [
Cell(r, c + 1), // Right
Cell(r + 1, c), // Down
Cell(r, c - 1), // Left
Cell(r - 1, c), // Up
];
// Create a single-cell group
const Group = (cell) => ({
minR: cell.r,
maxR: cell.r + 1,
minC: cell.c,
maxC: cell.c + 1,
cells: new Set([cell])
});
// Merge two groups into a new one
Group.merge = (g1, g2) => ({
minR: Math.min(g1.minR, g2.minR),
maxR: Math.max(g1.maxR, g2.maxR),
minC: Math.min(g1.minC, g2.minC),
maxC: Math.max(g1.maxC, g2.maxC),
cells: new Set([ ...g1.cells, ...g2.cells ])
});
// Take a grid and slice out the part covered by a group
Group.extractFromGrid = grid => ({ minR, maxR, minC, maxC }) => grid
.slice(minR, maxR)
.map(row => row.slice(minC, maxC));
// Create all cells with their values
const grid = getData();
const allCells = grid.flatMap(
(row, ri) => row.map(
(value, ci) => Cell(ri, ci)
)
);
const groupPerCell = new Map();
allCells.forEach(current => {
const inIsland = grid[current.r][current.c] !== "";
if (inIsland) {
const newGroup = Cell
.neighbors(current)
.filter(c => groupPerCell.has(c))
.map(c => groupPerCell.get(c))
.reduce(Group.merge, Group(current));
// Store a reference to the group for each member
newGroup.cells.forEach(c => {
groupPerCell.set(c, newGroup);
});
}
});
const allGroups = [...new Set(groupPerCell.values())];
const allValues = allGroups.map(Group.extractFromGrid(grid));
console.log(allValues);
function memo(f, hash) {
const cache = {};
return (...args) => {
const k = hash(args);
if (!cache[k]) cache[k] = f(...args);
return cache[k];
}
}
function getData() { return [
["col1", "col2", "col3", "col4", "col5", "col6", "col7", "col8", "col9"],
["", "", "", "", "", "", "", "", ""],
[1, 2, 3, "", "", "", "", "", ""],
[4, 5, 6, "", "", "a", "b", "", ""],
[7, 8, 9, "", "", "c", "d", "", 1],
["", "", "", "", "", "", "", "", 2],
["", "", "z", "y", "", "", "", "", 3],
["", "x", "w", "v", "", 7, 7, 7, ""],
["", "", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", "", ""],
["", "A1", "B1", "", "", "", "", "", ""],
["", "A2", "B2", "C2", "", "", "HELLO", "", ""]
]; }
推荐阅读
- node.js - Command Cooldown 1 minute not working discord bot
- assembly - 如何从汇编程序实模式源代码转到可启动闪存驱动器和光盘?
- c - 使用 memcpy 移动数组中的元素是否安全?
- python - 将图像转换为灰度python
- python - AttributeError:“NoneType”对象没有属性“信念”
- python - 请求设置,但未配置设置
- .net - 如何启用 dotnet https 在 localhost 中进行开发
- mysql - 不同表 mySql 中的最后插入 id
- amazon-web-services - AWS Cognito - PreTokenGeneration 在令牌刷新时省略 clientMetadata 参数
- python - R 的弦图的 Python 实现,带有数字以可视化集群和特征