JavaScript:如何创建多维数组?(需要代码示例)

5

我有一个10行10列的表格。我想定义一个数组,在该数组中可以将值放置在例如第5行,第3列的位置。

这个值本身是一个带有更多条目的数组。而这个数组的条目也是一个数组。

例子:

Row 1, column 1:
   My text 1, Link to text 1
   My text 2, Link to text 2

Row 4, column 5:
   My text 3, Link to text 3

Row 6, column 2:
   My text 1, Link to text 1
   My text 2, Link to text 2
   My text 3, Link to text 3
   My text 4, Link to text 4

并不是每个表格条目都需要被定义。一个表格元素可以有多个条目。一个条目由两个值组成:文本和文本的链接。
HTML表格已经定义好了。现在我想用上面的值(链接)来填充它。
我的问题是,如何创建一个有效的数据结构,以便我可以轻松地找到具有条目的表格位置(可能无需循环10行10列)。对于每个条目,我想获得文本+链接列表。
还有如何访问/读取我定义的每个条目。(我没有问题将值放置到我的HTML表格中。)
如果有人能给我一些代码示例,告诉我如何设置这样的数据结构,我会非常感激。
4个回答

3
var multiArray = [ ['element 0, 0', 'element 0, 1', 'element 0, 2'], ['element 1, 0', 'element 1, 1']];

编辑 每个[]中的符号都是一个数组,所以你只需要将它们组合成另一个数组即可。

等等其他内容...


在JS中,拥有相同长度的列并不重要,我喜欢这样。 - haynar
我是否正确理解,使用这种表示法,即使我不需要某个字段,我也必须定义每个表格的行和列? - Enkidu
@Enkidu,你说的“即使我不需要某个字段”是什么意思? - haynar

1

如果内存不是问题,只需使用数组的数组。

var table = [];
table.length = 10; // 10 rows;

for (var i = 0; i < array.length; i++) {
    table[i] = [];
    table[i].length = 20; // 20 columns for each row.
}

如果表格很大但只有很少的单元格被使用,您还可以使用哈希表的哈希。
var table = {};
table.rowCount = 10; // there're 10 rows

table[1] = {}
table[1].columnCount = 20 // 20 cells for row 1
table[1][3] = "hello world";

// visit all cells
for (var row in table) {
    for (var column in table[row] {
        console.log(table[row][column]);
    }
}

你甚至可以混合使用哈希和数组。


我的第二个例子就是我已经在尝试的。我没有问题附加一个简单的字符串,例如 "table[1][3] = "hello world";"。但是我遇到了附加数组的问题。我尝试过 table[1][3] = new Array( new Array( 'text1', 'link1'), new Array( 'text2', 'link2' ) ); 但我不知道如何访问这些值...顺便说一下,除了 "new Array()",我还可以写成 [ a, b ] 吗? - Enkidu

1
你可以创建一个简单的包装器来使调用方便:http://jsfiddle.net/QRRXG/2/
多维数组就是另一个数组中的数组。因此,您可以构建一个包含10个数组的数组,其中每个数组又包含10个数组。然后使用 arr[i][j] 获取一个数组。
项目可以表示为对象:
{ name: "foo", link: "bar" }

那么这样的项目可以像obj.nameobj.link一样进行解析。

var multi = (function() {
    var data = [];

    // initialize
    for(var i = 0; i < 10; i++) {
        data[i] = [];
        for(var j = 0; j < 10; j++) {
            data[i][j] = [];
        }
    }

    return {
        get: function(i, j) { // will return an array of items
            return data[i][j];
        },

        push: function(i, j, v) { // will add an item
            data[i][j].push(v);
        },

        clear: function(i, j) { // will remove all items
            data[i][j] = [];
        },

        iterateDefined: function(f) {
            for(var i = 0; i < 10; i++) {
                for(var j = 0; j < 10; j++) {
                    if(data[i][j].length > 0) {
                        f(data[i][j], i, j);
                    }
                }
            }
        }
    };
})();

你可以这样使用:

multi.push(2, 3, { name: "foo", link: "test1" });
multi.push(2, 3, { name: "bar", link: "test2" });

multi.push(1, 4, { name: "haz", link: "test3" });

multi.push(5, 7, { name: "baz", link: "test4" });
multi.clear(5, 7);


console.log(multi.get(2, 3)); // logs an array of 2 items
console.log(multi.get(1, 4)); // logs an array of 1 item
console.log(multi.get(5, 7)); // logs an array of 0 items

console.log(multi.get(2, 3)[0].name); // logs "foo"
console.log(multi.get(2, 3)[1].link); // logs "test2"


multi.iterateDefined(function(items, i, j) {
    console.log(items, i, j); // will log two times
});

这看起来非常聪明!:) 但我的问题是,我不想访问表中的某个字段,而只想获取定义字段的值。(可能只有100个字段中的20个有值。) - Enkidu
太好了!谢谢!看起来就是我想要的! :) - Enkidu

1
创建一个实用程序对象:
var DataTable = {
    source: [],
    setEntry: function(i,j,e) {
      var o ;
        if( !!! ( o = this.source[i] )  ) o = this.source[i] = [] ;
        o[j] = e ;
        return this ;
    },
    getEntry: function(i,j) {
      var o, e = null ;
        if( !! ( o = this.source[i] ) ) e = o[j] || null ;
      return e ;
    }
} ;

其他答案似乎建议放置虚拟的Array作为未使用坐标的占位符。这样做虽然不是错误的,但是是不必要的:如果您在JavaScript中设置一个索引超出当前范围的Array条目,则Array实际上会填充undefined值。
var a = [ ] ; // a length is 0
    a[1024] = 1 // a length is now 1025, a[1] is undefined

然后添加所需的值:
DataTable.setEntry( 1, 1, ["My text 1","Link to text 1","My text 2","Link to text 2"] )
.setEntry( 4, 5, ["My text 3","Link to text 3"] ) 
//..
;

以下控制语句将返回坐标的Array值或null(如果DataTable.source不包含给定坐标的嵌套Array):
console.log("(!!) d.source: " + DataTable.getEntry(4,5) ) ;
console.log("(!!) d.source: " + DataTable.getEntry(1,1) ) ;
console.log("(!!) d.source: " + DataTable.getEntry(0,0) ) ;

在此尝试:


更新:

这是一个相当旧的帖子,但由于我收到了一条评论要求解释片段,因此在此更新了类语法和更多注释:

class DataTable {

  data = [];
  
  constructor() {
    // bind methods to this instance
    this.setEntry = this.setEntry.bind(this);
    this.getEntry = this.getEntry.bind(this);
  }
  
  // set an entry at the given coordinates (row and column index pair)
  setEntry(rowIndex, columnIndex, value) {
    let row = this.data[rowIndex];
    
    // create the row lazily if it does not exist yet
    if(typeof row === 'undefined') {
      this.data[rowIndex] = [];
      row = this.data[rowIndex];
    }
    // set the value
    row[columnIndex] = value;
  }
  
  // get the entry at the given coordinates (row and column index pair)
  getEntry(rowIndex, columnIndex) {
    const row = this.data[rowIndex];
    // test if the row is defined; if not return null.
    if(typeof row === 'undefined') { return null; }
    else {
      // return the value or fall back to null
      return row[columnIndex] || null;
    }
  }

}

const d = new DataTable();
d.setEntry(1, 1, ["My text 1","Link to text 1","My text 2","Link to text 2"]);
d.setEntry(4, 5, ["My text 3","Link to text 3"]);

console.log(`d.getEntry(4, 5) = ${d.getEntry(4, 5)}`);
console.log(`d.getEntry(1, 1) = ${d.getEntry(1, 1)}`);
console.log(`d.getEntry(0, 0) = ${d.getEntry(0, 0)}`);


谢谢。我以前从未使用过这种编码方式,但它似乎正是我正在寻找的。 - Enkidu
正是我所需要的。如果可能的话,您能否解释一下这部分的setEntry和getEntry?!! - Dileephell
1
@Dileephell 我使用类语法添加了一个更新,并添加了一些注释。 - FK82

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接