Búsqueda de sitios web

ordenación - ¿Cuál es la manera más eficiente de ordenar una tabla HTML mediante JavaScript?


Estoy escribiendo algo de JS para ordenar una tabla HTML: la tabla HTML tiene una fila de encabezado, al hacer clic en el encabezado de una columna, se ordenan las filas según esa columna. Mi algoritmo general es el siguiente:

  1. Convertir HTML en un arreglo de JavaScript.
  2. Ordenar arreglo de JavaScript.
  3. Reconvertir un array de JavaScript a tabla HTML.

En este momento, mi código reemplaza todos los elementos innerHTML de la tabla. Básicamente, después de que ordena el array de JS, toca cada nodo de la tabla, reescribiendo su valor innerHTML. Siento que podría haber una manera más eficiente de hacer esto, pero no puedo pensar en ella.

EDITAR :

Aquí está el código que hace la parte (3) del algoritmo descrito arriba. He eliminado las partes irrelevantes (solo algunas transformaciones de cadenas). Los índices son un poco extraños porque omití la fila del encabezado cuando convertí la tabla en un arreglo, así que estoy compensando eso al reescribir la tabla.

for (var i = 0; i < numRows-1; i++){
 for (var j = 0; j < numCols; j++){
        var arrCell = tableArr[i][cols[j]];
        tableEl.rows[i+1].cells[j].innerHTML = arrCell;
    }
}

Respuesta #1

Usa un arreglo para ordenar los valores y un fragmento de documento para realizar la actualización.

function sortRows(tbody, compare, sortDesc) {
    //convert html collection to array
    var rows = [].slice.call(tbody.rows);
    //sort to desired order
    rows.sort(compare);
    if (sortDesc) {
        rows.reverse();
    }
    //update table
    var fragment = document.createDocumentFragment();
    rows.forEach(function (row) {
        fragment.appendChild(row);
    });
    tbody.appendChild(fragment);
}

La complejidad estará en la función de comparación. Necesitarás tener en cuenta el índice de la columna y cualquier conversión de tipos y almacenamiento en caché que desees.

Este es un ejemplo básico que convierte el contenido de texto de la celda en un número entero.

function sortTable(table, columnIndex) {
    while (table && table.tagName !== 'TABLE') {
        table = table.parentNode;
    }
    if (table) {
        sortRows(table.tBodies[0], function compare(topRow, bottomRow) {
            var topValue = parseInt(topRow.cells[columnIndex].textContent, 10);
            var bottomValue = parseInt(bottomRow.cells[columnIndex].textContent, 10);
            return (topValue - bottomValue);
        });
    }
}

function sortRows(tbody, compare, sortDesc) {
    //convert html collection to array
    var rows = [].slice.call(tbody.rows);
    //sort to desired order
    rows.sort(compare);
    if (sortDesc) {
        rows.reverse();
    }
    //update table
    var fragment = document.createDocumentFragment();
    rows.forEach(function (row) {
        fragment.appendChild(row);
    });
    tbody.appendChild(fragment);
}
<table>
    <thead>
        <tr><th onclick="sortTable(this, 0)">Sort</th><th onclick="sortTable(this, 1)">Sort</th></tr>
    </thead>
    <tbody>
        <tr><td>1</td><td>25</td></tr>
        <tr><td>3</td><td>12</td></tr>
        <tr><td>2</td><td>40</td></tr>
        <tr><td>10</td><td>25</td></tr>
    </tbody>
</table>

Respuesta #2

Podrías eliminar las filas del DOM, hacer la ordenación y luego volver a agregarlas al DOM.

var tbody = table.tBodies[0];

var placeholder = document.createElement('tbody');
table.replaceChild(placeholder, tbody);

//sort rows in tbody

table.replaceChild(tbody, placeholder);