Сортировка значений таблицы по возрастанию и по убыванию с помощью JavaScript

1

У меня есть следующая таблица, которая пытается сортировать по возрастанию и убыванию порядка onclick со следующим кодом JavaScript:

function sortTable(n) {
  var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
  table = document.getElementById("myTable");
  switching = true;
  //Set the sorting direction to ascending:
  dir = "asc";
  /*Make a loop that will continue until
  no switching has been done:*/
  while (switching) {
    //start by saying: no switching is done:
    switching = false;
    rows = table.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")[n];
      y = rows[i + 1].getElementsByTagName("TD")[n];
      /*check if the two rows should switch place,
      based on the direction, asc or desc:*/
      if (dir == "asc") {
        if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
          //if so, mark as a switch and break the loop:
          shouldSwitch = true;
          break;
        }
      } else if (dir == "desc") {
        if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
          //if 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;
      //Each time a switch is done, increase this count by 1:
      switchcount++;
    } else {
      /*If no switching has been done AND the direction is "asc",
      set the direction to "desc" and run the while loop again.*/
      if (switchcount == 0 && dir == "asc") {
        dir = "desc";
        switching = true;
      }
    }
  }
}
<div class="table-responsive">
  <table class="table table-striped" id="myTable">
    <tr>
      <th onclick="sortTable(0)">Date <i class='fa fa-caret-down'></i></th>
      <th onclick="sortTable(1)">Views <i class='fa fa-caret-down'></i></th>
      <th onclick="sortTable(2)">Clicks <i class='fa fa-caret-down'></i></th>
      <th onclick="sortTable(3)">CTR <i class='fa fa-caret-down'></i></th>
      <th onclick="sortTable(4)">Earned <i class='fa fa-caret-down'></i></th>
      <th onclick="sortTable(5)">eCPM <i class='fa fa-caret-down'></i></th>
    </tr>
    <tr>
      <td>2017-11-30</td>
      <td>4133</td>
      <td>3</td>
      <td>0.07%</td>
      <td>$0.03</td>
      <td>$0.0073</td>
    </tr>
    <tr>
      <td>2017-11-29</td>
      <td>8340</td>
      <td>5</td>
      <td>0.06%</td>
      <td>$0.05</td>
      <td>$0.006</td>
    </tr>
    <tr>
      <td>2017-11-28</td>
      <td>7410</td>
      <td>5</td>
      <td>0.07%</td>
      <td>$0.025</td>
      <td>$0.0034</td>
    </tr>
    <tr>
      <td>2017-11-27</td>
      <td>3796</td>
      <td>2</td>
      <td>0.05%</td>
      <td>$0.01</td>
      <td>$0.0026</td>
    </tr>
    <tr>
      <td>2017-11-26</td>
      <td>4005</td>
      <td>2</td>
      <td>0.05%</td>
      <td>$0.01</td>
      <td>$0.0025</td>
    </tr>
    <tr>
      <td>2017-11-25</td>
      <td>2070</td>
      <td>2</td>
      <td>0.1%</td>
      <td>$0.01</td>
      <td>$0.0048</td>
    </tr>
    <tr>
      <td>2017-11-24</td>
      <td>1016</td>
      <td>6</td>
      <td>0.59%</td>
      <td>$0.03</td>
      <td>$0.0295</td>
    </tr>
    <tr>
      <td>2017-11-23</td>
      <td>1503</td>
      <td>4</td>
      <td>0.27%</td>
      <td>$0.02</td>
      <td>$0.0133</td>
    </tr>
    <tr>
      <td>2017-11-22</td>
      <td>1665</td>
      <td>11</td>
      <td>0.66%</td>
      <td>$0.055</td>
      <td>$0.033</td>
    </tr>
    <tr>
      <td>2017-11-21</td>
      <td>1340</td>
      <td>10</td>
      <td>0.75%</td>
      <td>$0.05</td>
      <td>$0.0373</td>
    </tr>
    <tr>
      <td>2017-11-20</td>
      <td>1489</td>
      <td>13</td>
      <td>0.87%</td>
      <td>$0.065</td>
      <td>$0.0437</td>
    </tr>
    <tr>
      <td>2017-11-19</td>
      <td>1745</td>
      <td>5</td>
      <td>0.29%</td>
      <td>$0.025</td>
      <td>$0.0143</td>
    </tr>
    <tr>
      <td>2017-11-18</td>
      <td>962</td>
      <td>5</td>
      <td>0.52%</td>
      <td>$0.025</td>
      <td>$0.026</td>
    </tr>
    <tr>
      <td>2017-11-17</td>
      <td>779</td>
      <td>8</td>
      <td>1.03%</td>
      <td>$0.04</td>
      <td>$0.0513</td>
    </tr>
  </table>
</div>

Проблема здесь в том, что она работает правильно с одинаковым количеством цифр, но не с разным количеством цифр. Например, если столбец содержит: 1, 5, 3

Он сортируется так, как ожидалось. 1, 3, 5 и 5, 3, 1

Но если столбец содержит: 5, 3, 11

Он сортируется как: 11, 3, 5 и 5, 3, 11

Как правильно их отсортировать?

  • 1
    Попробуйте использовать parseInt (); Как parseInt (x.innerHTML.toLowerCase ());
  • 0
    Вы сравниваете строки '1', '11','2' etc.. не числа 1,2,11,etc...
Показать ещё 1 комментарий
Теги:
sorting

1 ответ

0

Поскольку у вас есть несколько разных форматов, то, что вы, вероятно, захотите сделать, это попытаться извлечь цифровую часть числа.

Вы можете попытаться сделать это с помощью RegExp, проверив общие числовые шаблоны и затем проанализируя простой номер. Если бы я архивировал это, у меня, вероятно, был бы массив различных функций сопоставления и преобразования для каждого поддерживаемого формата.

Что-то вроде этого:

const patterns = [
      { test: /\$[0-9\.,]+/, transform: str => parseFloat(str.replace(/[$,]/g, '')) },
      { test: /[0-9\.,]+%/, transform: str => parseFloat(str.replace(/[%,]/g, '')) }
    ];
    
const convert = str => {
  const pattern = patterns.find(({ test }) => test.test(str));
  
  return pattern && pattern.transform(str) || str;
};

const converted = ['$1,234.56', '1,234.56%', 'not a num'].map(str => convert(str));
console.log(converted);

Затем, для каждого поля, пропустите его через все шаблоны, пока не найдете совпадение, не конвертируйте их, а затем выполните числовую сортировку. Вы также можете оставить те, которые не преобразуются в виде строк, и пусть это просто делает для них похожий на строку тип.

В вашем коде, если вы использовали что-то вроде меня, вы просто изменили бы сравнительные строки на что-то вроде этого:

if (convert(x.innerHTML.toLowerCase()) > convert(y.innerHTML.toLowerCase()))

Кроме того, совет для дат: я бы рекомендовал преобразовать даты в временные метки или общий формат (например, YYYY-MM-DD HH:MM:SS, который является самым большим до наименьшего), который затем позволит вам правильно сравнивать и сортировать несколько форматов даты в одном столбце.


Ниже был оригинальный ответ, который не учитывал символы с номерами.

Ваша проблема в том, что вы выполняете сравнение строк вместо численного сравнения.

Сравнение строк будет сортировать строки так же, как и алфавиты. Например, все, что начинается с 1, всегда будет предшествовать чему-либо, начинающемуся с 2, даже если это "1365872685623876723" против "2".

Вместо этого измените эти строки:

x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()

Сначала проанализировать их на номера с помощью parseInt():

parseInt(x.innerHTML.toLowerCase()) > parseInt(y.innerHTML.toLowerCase())

Это сделает его численным.

  • 0
    Это будет работать только в том случае, если значения для сортировки являются полными числами. Сортировка столбцов со значениями % и $ выиграет, так как parseInt() не решает проблему. Требуемое решение должно быть более сложным, когда OP, скорее всего, должен хранить фактическое необработанное число внутри атрибута данных или аналогичного и сортировать его вместо этого. Хотя десятичные значения могут потенциально вызывать другое решение, отличное от parseInt
  • 0
    Хм, хороший улов. Я не видел никакой информации об этом в тексте, но более внимательный взгляд на пример данных есть. Веселье. = р
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню