JavaScript使用限制对列表进行排序

时间:2017-11-08 15:34:02

标签: javascript html css list sorting

我正在Electron制作一个应用程序,并有一个名单和位置的客户列表。我有一个允许用户添加客户的按钮,但是这样做时,表格会显示索引。我有另一个按字母顺序对名称进行排序的按钮,但如果有行中有索引,则会先显示这些...

我想要的是一些限制,当排序而不是开头时,将带有(0)(1)的行放在列表的末尾。

实施例: adding customers sorting the customers

客户排序正确,但是当我希望在0之前有单词时,所有带0的行都在带有实际单词的行之前。

代码: 出于某种原因,在这段代码中,它实际上并没有显示0或1索引,但它仍然在带有文本的行之前没有任何内容排序......

const back = document.getElementById('back');
const cust = document.getElementById('cust');
const custDiv = document.getElementById('custDiv');
const addCust = document.getElementById('addCust');
const inv = document.getElementById('inv');
const invDiv = document.getElementById('invDiv');
const addItem = document.getElementById('addItem');


// add customer
function appendRowCust() {
  var custList = document.getElementById('custList'), // table reference
    row = custList.insertRow(custList.rows.length), // append table row
    i;
  // insert table cells to the new row
  for (i = 0; i < custList.rows[0].cells.length; i++) {
    createCell(row.insertCell(i), i, 'row');
  }
}
// create DIV element and append to the table cell
function createCell(cell, text, style) {
  var div = document.createElement('div'), // create DIV element
    txt = document.createTextNode(''); // create text node
  div.appendChild(txt); // append text node to the DIV
  div.setAttribute('class', style); // set DIV class attribute
  div.setAttribute('className', style); // set DIV class attribute for IE (?!)
  cell.appendChild(div); // append DIV to the table cell
}


// sort customers 
function sortCustTable() {
  var custList, rows, switching, i, x, y, shouldSwitch;
  custList = document.getElementById("custList");
  switching = true;
  /* Make a loop that will continue until
  no switching has been done: */
  while (switching) {
    // Start by saying: no switching is done:
    switching = false;
    rows = custList.getElementsByTagName("TR");
    /* Loop through all table rows (except the
    first, which contains table headers): */
    for (i = 1; i < (rows.length - 1); i++) {
      // Start by saying there should be no switching:
      shouldSwitch = false;
      /* Get the two elements you want to compare,
      one from current row and one from the next: */
      x = rows[i].getElementsByTagName("TD")[0];
      y = rows[i + 1].getElementsByTagName("TD")[0];
      // Check if the two rows should switch place:
      if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
        // I so, mark as a switch and break the loop:
        shouldSwitch = true;
        break;
      }
    }
    if (shouldSwitch) {
      /* If a switch has been marked, make the switch
      and mark that a switch has been done: */
      rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
      switching = true;
    }
  }
}
table {
  background-color: black;
  color: white;
} 

tr:nth-child(even) {
  background-color: #656565;
}
tr:nth-child(odd) {
  background-color: #505050;
}

td {
  width: 300px;
  max-width: 300px;
  height: 30px;
  text-align: center;
}
<div id="custDiv">
  <div class="addBtns">
    <button id="addCust" onclick="appendRowCust()">add customer</button>
  </div>

  <div style="width: 355px; margin: 0 auto; height: 50px;">
    <button id="sortCust" onclick="sortCustTable()">sort</button>
  </div>

  <div class="custScroll">
    <table id="custListTop">
      <tr>
        <td contenteditable="false">Customers</td>
        <td contenteditable="false">Main Location</td>
      </tr>
    </table>
    <table id="custList" contenteditable="true">
      <tr>
        <td>Someone</td>
        <td>something</td>
      </tr>
    </table>
  </div>

</div>

3 个答案:

答案 0 :(得分:1)

首先,您需要总结一下您的规格。根据我的理解,他们是这样的:

  • 您的表格需要按字典顺序按第一列排序......
  • 数字或空字符串除外,需要在列的最后排序。

现在,@ IrkenInvader给出的答案是正确的,指出您不需要编写自己的排序算法,但就实现正确有效的解决方案而言,请考虑使用内置算法{{ 1}}做了一些修改:

Array#sort()

我选择仅使用ECMAScript 5功能,因为代码中的注释表示要支持Internet Explorer。我注意到你正在使用function sortCustTable() { var custList = document.getElementById('custList'); var rows = custList.getElementsByTagName('tr'); var parent = rows[0].parentElement; var length = rows.length; var data = [], ref, charCodes; for (var index = 0; index < length; index++) { ref = { row: rows[index], value: rows[index].firstElementChild.textContent.toUpperCase() }; if (ref.value === '') { ref.value = 'k'; // will sort after everything else, including numbers } else if (!isNaN(ref.value)) { charCodes = ref.value.split('').map(function (char) { return Number(char) + 97; // charCode for 'a' }); // for example, '05' would become 'af' ref.value = String.fromCharCode.apply(String, charCodes); } data.push(ref); } data.sort(function (a, b) { if (a.value > b.value) return 1; if (a.value < b.value) return -1; return 0; }); for (var index = 0; index < length; index++) { parent.appendChild(data[index].row); } } ,所以如果你觉得更容易,可以使用ES6进行修改。

将其与其余代码放在一起,您可以在下面看到它。我在表格中添加了一些更多的默认值,让您了解它的工作原理:

const
const back = document.getElementById('back');
const cust = document.getElementById('cust');
const custDiv = document.getElementById('custDiv');
const addCust = document.getElementById('addCust');
const inv = document.getElementById('inv');
const invDiv = document.getElementById('invDiv');
const addItem = document.getElementById('addItem');

// add customer
function appendRowCust() {
  var custList = document.getElementById('custList'), // table reference
    row = custList.insertRow(custList.rows.length), // append table row
    i;
  // insert table cells to the new row
  for (i = 0; i < custList.rows[0].cells.length; i++) {
    createCell(row.insertCell(i), i, 'row');
  }
}
// create DIV element and append to the table cell
function createCell(cell, text, style) {
  var div = document.createElement('div'), // create DIV element
    txt = document.createTextNode(''); // create text node
  div.appendChild(txt); // append text node to the DIV
  div.setAttribute('class', style); // set DIV class attribute
  div.setAttribute('className', style); // set DIV class attribute for IE (?!)
  cell.appendChild(div); // append DIV to the table cell
}


// sort customers 
function sortCustTable() {
  var custList = document.getElementById('custList');
  var rows = custList.getElementsByTagName('tr');
  var parent = rows[0].parentElement;
  var length = rows.length;
  var data = [], ref, charCodes;

  for (var index = 0; index < length; index++) {
    ref = {
      row: rows[index],
      value: rows[index].firstElementChild.textContent.toUpperCase()
    };

    if (ref.value === '') {
      ref.value = 'k'; // will sort after everything else, including numbers
    } else if (!isNaN(ref.value)) {
      charCodes = ref.value.split('').map(function (char) {
        return Number(char) + 97; // charCode for 'a'
      });

      // for example, '05' would become 'af'
      ref.value = String.fromCharCode.apply(String, charCodes);
    }

    data.push(ref);
  }

  data.sort(function (a, b) {
    if (a.value > b.value) return 1;
    if (a.value < b.value) return -1;
    return 0;
  });

  for (var index = 0; index < length; index++) {
    parent.appendChild(data[index].row);
  }
}
table {
  background-color: black;
  color: white;
} 

tr:nth-child(even) {
  background-color: #656565;
}
tr:nth-child(odd) {
  background-color: #505050;
}

td {
  width: 300px;
  max-width: 300px;
  height: 30px;
  text-align: center;
}

现在,为了澄清为什么会这样排序,让我们看一下表值以及我们在排序之前如何修改它们:

<div id="custDiv">
  <div class="addBtns">
    <button id="addCust" onclick="appendRowCust()">add customer</button>
  </div>

  <div style="width: 355px; margin: 0 auto; height: 50px;">
    <button id="sortCust" onclick="sortCustTable()">sort</button>
  </div>

  <div class="custScroll">
    <table id="custListTop">
      <tr>
        <td contenteditable="false">Customers</td>
        <td contenteditable="false">Main Location</td>
      </tr>
    </table>
    <table id="custList" contenteditable="true">
      <tr>
        <td>Someone</td>
        <td>something</td>
      </tr>
      <tr>
        <td>Somebody</td>
        <td>1</td>
      </tr>
      <tr>
        <td></td>
        <td>1</td>
      </tr>
      <tr>
        <td>0</td>
        <td>1</td>
      </tr>
      <tr>
        <td>someone else</td>
        <td>1</td>
      </tr>
      <tr>
        <td>somebody else</td>
        <td>1</td>
      </tr>
    </table>
  </div>

</div>

我们将丢弃第二列,因为我们不使用它,并将所有客户也设置为大写:

 Customers     | Main Location
---------------+---------------
 Someone       | something
 Somebody      | 1
               | 1
 0             | 1
 someone else  | 1
 somebody else | 1

接下来我们检查每个字符串是否为空,如果是,我们给它赋值 Customers | ---------------| SOMEONE | SOMEBODY | | 0 | SOMEONE ELSE | SOMEBODY ELSE |

'k'

最后,我们通过将数字值添加到97来修改任何数字,并将生成的 Customers | ---------------| SOMEONE | SOMEBODY | k | 0 | SOMEONE ELSE | SOMEBODY ELSE | 转换为字符:

charCode

按字典顺序排序,我们得到:

 Customers     |
---------------|
 SOMEONE       |
 SOMEBODY      |
 k             |
 a             |
 SOMEONE ELSE  |
 SOMEBODY ELSE |

回到原始值,我们得到:

 Customers     |
---------------|
 SOMEBODY      |
 SOMEBODY ELSE |
 SOMEONE       |
 SOMEONE ELSE  |
 a             |
 k             |

答案 1 :(得分:1)

我添加了一个从单元格内容数组中绘制表格的方法。对rows进行排序并调用drawTableRows将以rows数组结束的任何顺序重新创建表。我添加了一些代码来每隔三行插入一次模拟数据,因此可以看到将数字排序到底部。

这是一个比我通常喜欢给出答案更大的变化,但我认为你可能会喜欢看到不同的方法。

var rows = [[ 'Someone', 'something' ]];

function drawTableRows() {
  var custList = document.getElementById('custList'); // table reference
  custList.innerHTML = '';
  
  for(var i = 0; i < rows.length; i++) {      
    var row = rows[i];
    var tableRow = custList.insertRow(i); // append table row    
        
    for(var j = 0; j < row.length; j++) {      
      createCell(tableRow.insertCell(j), row[j], 'row');      
    }
  }
}

// add customer
function appendRowCust(customer = 0, location = 1) {
  //throw in mock data every 3 rows (just a test - remove later)
  if(rows.length % 3 === 0) {
    customer = 'Real customer ' + rows.length;
    location = 'Real location ' + rows.length;
  }
  
  rows.push([customer, location]);
  drawTableRows();
}

// create DIV element and append to the table cell
function createCell(cell, text, style) {
  var div = document.createElement('div'), // create DIV element
    txt = document.createTextNode(text); // create text node
  div.appendChild(txt); // append text node to the DIV
  div.setAttribute('class', style); // set DIV class attribute
  div.setAttribute('className', style); // set DIV class attribute for IE (?!)
  cell.appendChild(div); // append DIV to the table cell
}

function sortCustTable() {
  rows.sort(function(a,b){
    //sort by first column
    var aVal = a[0];
    var bVal = b[0];
    
    //sort by cell content - if content is a number push to bottom.
    if((bVal > aVal) || !isNaN(bVal)) {
      return -1;
    }    
    if((aVal > bVal) || !isNaN(aVal)) {
      return 1;
    }    
    return 0;
  });
  
  drawTableRows();
}
table {
  background-color: black;
  color: white;
}

tr:nth-child(even) {
  background-color: #656565;
}

tr:nth-child(odd) {
  background-color: #505050;
}

td {
  width: 300px;
  max-width: 300px;
  height: 30px;
  text-align: center;
}
<div id="custDiv">
  <div class="addBtns">
    <button id="addCust" onclick="appendRowCust()">add customer</button>
  </div>

  <div style="width: 355px; margin: 0 auto; height: 50px;">
    <button id="sortCust" onclick="sortCustTable()">sort</button>
  </div>

  <div class="custScroll">
    <table id="custListTop">
      <tr>
        <td contenteditable="false">Customers</td>
        <td contenteditable="false">Main Location</td>
      </tr>
    </table>
    <table id="custList" contenteditable="true">
      <tr>
        <td>Someone</td>
        <td>something</td>
      </tr>
    </table>
  </div>

</div>

答案 2 :(得分:0)

您可以通过尝试强制转换为数字并确定当前迭代值是否为整数来过滤掉差异。然后简单地对两个结果集进行排序和连接。

Router: 257219241 accepting request POST http://localhost:8890/provider 
Route matches: Route[ path:/provider pattern:null handler:io.vertx.core.Handler$$NashornJavaAdapter@69b539e failureHandler:null order:0 methods:[POST]]@32182409 
Calling the  handler 
body=null

要优化上述内容,您可以过滤一次,如果结果为false,则推送到单独声明的数组 var list = [0, 2, "2", "0", 1, 2, "a", "b", "c"], numeric = list.filter(value => Number.isInteger(+value)), alpha = list.filter(value => !Number.isInteger(+value)), result = alpha.sort().concat(numeric.sort());

alpha

确定两者之间的差异将是微观优化,我怀疑在任何情况下都是必要的,前者更加冗长和清晰。我的建议是使用第一个选项。

   var list = [0, 2, "2", "0", 1, 2, "a", "b", "c"],
   alpha = [],
   numeric = list.filter(value => {
     let torf = Number.isInteger(+value);
     if (!torf) alpha.push(value);
     return torf;
   }),
   result = alpha.sort().concat(numeric.sort());