【问题标题】:How to compare cells in JavaScript table to each other and test for equality? How does indexOf work?如何比较 JavaScript 表格中的单元格并测试是否相等? indexOf 是如何工作的?
【发布时间】:2014-06-22 02:54:41
【问题描述】:

我在我的 HTML 代码中创建了一个表格。它有 9 列和 13 行。它被一个 JavaScript 循环完全填满,该循环用几个数组中的人名填充它。但是,我想添加一个验证步骤,以确保一行中没有两个单元格具有相同的值,并且每个单元格的值不会在其正下方的单元格中重复。

由于我只能以 NodeList 的形式访问表中单元格的值,因此我决定将其制成一个数组,以使用 IndexOf 属性在数组中进行搜索:

var table1 = document.getElementsByTagName("td");
var table1Array = [];    //number of "td" elements on page
for (i = 0; i < 117; i++) {
    table1Array[i] = table1[i].innerHTML;
}

我不知道更优雅的方法(这里有点像初学者)。所以我设置了一些嵌套循环来将每个单元格与我创建的行数组中的每个元素进行比较(对于所有 13 行):

function validateCells() {
for (i = 0; i < 117; i = i + 9) { //increment for going to next column (after 9 cells or elements in array)
    for (j = 0; j < 8; j++) {
        var curCell = table1Array[i];
        var curRow = [];         //I'm ignoring the first column which is "date", so it has 8 elements rather than 9
        for (k = 0; k < 8; k++) {
            curRow[k] = document.getElementById("row" + j).children[k].innerHTML;
        }
        if (curRow.indexOf(curCell) != -1) {
            curCell = "CONFLICT"; //trying to change value in table. Doesn't work.
        }
    }
}
}

很遗憾,这行不通。我什至不知道修改 curCell 引用变量的值是否真的会改变 table1Array 在该位置的值,如果它会改变表中的数据则更少。

我是否正确使用了 indexOf 属性?我是使用 != 比较运算符还是 !==? indexOf 是否将索引返回为 a 是否还有其他更简单、更优雅的方法来执行此操作?我刚开始使用 jQuery,也许它可以帮助简化代码并减少出错的可能性。

对于所有问题,我很抱歉,我真的很想了解这一切是如何运作的。谢谢!

【问题讨论】:

  • 当你创建一个像var curRow = [8]; 这样的数组时,它会创建一个只有一个元素的数组,其值为 8
  • 所以只需要var curRow = []; 来声明数组?第一个也是?我必须将其更改为 var table1Array = []; ?
  • 表有一个 rows 集合,行有一个 cells 集合。您应该能够使用它们的索引访问相邻行中的单元格(例如,将 rows[i].cells[j] 的内容与 rows[i+1].cells[j] 进行比较。
  • @user96872 是的,这将是一个改进,而且,当给定的索引尚不存在时,通常使用Array.prototype.push而不是直接在数组中的索引处设置值。

标签: javascript jquery arrays loops indexof


【解决方案1】:

你应该得到一个行数组,每一行都是一个单元格数组。这样验证就容易多了。我不确定你想如何表现冲突。在这个演示中,我只是用红色突出显示了重复的单元格(冲突的)(至少我喜欢这种显示冲突而不是修改冲突单元格的文本)。

HTML:

<table>
  <tr><td>1</td><td>2</td><td>3</td></tr>
  <tr><td>1</td><td>5</td><td>6</td></tr>
  <tr><td>7</td><td>8</td><td>7</td></tr>
  <tr><td>8</td><td>9</td><td>10</td></tr>
</table>
<button>Check constraints</button>

CSS:

td {
  width:100px;
  height:50px;
  border:1px solid black;
}
table {
  border:1px solid black;
  border-collapse:collapse;
}
td.invalid {
  background:red;
}

JS:

$('td').attr('contenteditable',true);
var cell;     
function highlight(){    
  $(arguments).toggleClass('invalid',true);
}
function checkConstraints(e){
  //reset style before re-checking
  $('td.invalid').toggleClass('invalid');
  //get rows as an array of array
  var rows = $('tr').map(function(elem,i){
      return [$(this).children('td').toArray()];
  }).toArray();        
  //loop through the rows
  for(var i = 0; i < rows.length; i++){
    cell = {};        
    for(var j = 0; j < rows[i].length; j++){
        var cellText = $(rows[i][j]).text();
        if(cell[cellText]) {  
            highlight(cell[cellText], rows[i][j]);                
        } else {
            cell[cellText] = rows[i][j];
        }
        if(i < rows.length - 1 && 
           cellText == $(rows[i+1][j]).text()){
           highlight(rows[i][j],rows[i+1][j]);
        }            
    }        
  }
}
$('button').click(checkConstraints);

Demo.

请注意,我为所有单元格设置了contenteditable (td),您可以将单元格文本编辑为您想要的内容,然后单击按钮来测试演示。

【讨论】:

  • 请注意,innerText 不是任何 W3C 标准的一部分,可能并非所有地方都支持(例如 Firefox)。
【解决方案2】:

您可以使用表格行和单元格集合进行迭代。下面对文本内容进行字面比较,您可能希望先处理文本以将其“规范化”为空白。

<table id="t0">
 <tr><td>foo<td>bar<td>fum</td>
 <tr><td>fum<td>bar<td>foo</td>
 <tr><td>foo<td>fum<td>fum</td>
</table>

<script>

compareRows(document.getElementById('t0'));

function compareRows(table) {
  var row, rows = table.rows;
  var cell, cells;
  var rowText;

  // For each row in the table
  for (var i=0, iLen=rows.length; i<iLen; i++) {
    row = rows[i];
    cells = row.cells;

    // Compare the text in each cell
    for (var j=0, jLen=cells.length; j<jLen; j++) {
      cell = cells[j];

      for (var k=0; k<jLen; k++)

        if (k != j && cells[k].textContent == cell.textContent) {
          // cell text is repeated in current row
          console.log('row ' + i + ' cell ' + j + ' text repeated in cell ' + k);
      }

      // Compare with the text in the cell immediately below (if there is one)
      if (i < iLen-2 && cell.textContent == rows[i+1].cells[j].textContent) {
        // cell text is repeated in next row
        console.log('row ' + i + ' cell ' + j + ' text repeated in row ' + (i+1));
      }
    }
  }
}
</script>

注意,连续出现重复的文字会被报两次。

上面使用了 textContent 属性,在某些用户代理中可能作为 innerText 支持。与 jQuery 替代方案相比,它还运行大约 10 times faster。

【讨论】:

  • 我忘记了 TABLE 元素支持的纯属性,最好使用它们而不是使用 jQuery 查询单元格。
  • 天才!我不知道 textContent 属性甚至存在!但是,关于空格的“规范化”文本是什么意思?我看到 textContent 属性返回指定节点 和 的所有后代的文本内容。它确实返回它们没有空格,这是你的意思吗? @RobG
  • @user96872 — textContent 属性可能返回比您想象的更多的空格,并且在不同的浏览器中可能会有所不同,因此最好说修剪前导和尾随空格并减少内部空格为单个,并可能将换行符转换为空格(如果应该比较相同)。
  • @RobG 如何将当前单元格作为 HTML 元素访问,以便更改其 CSS 属性?我试图突出显示这些单元格。谢谢!
猜你喜欢
  • 2019-03-08
  • 2012-02-15
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-23
相关资源
最近更新 更多