Этот вопрос связан со сценарием и основан на нем: Как отсортировать многомерный массив по нескольким столбцам в JavaScript? . Мое решение работало в то время (или я так полагаю), но после внесения ряда изменений в наш пользовательский тег, чтобы сделать его совместимым с браузерами, у меня появилась новая проблема.
Итак, у меня есть следующий фрагмент кода. Мои извинения за длину; это было настолько, насколько я мог бы упростить это, все еще повторяя проблему:
<table border=1>
<tr style="font-weight:bold;">
<td>Begin Text</td>
<td>Begin Number</td>
<td>Sorted Text</td>
<td>Sorted Number</td>
</tr>
<tr>
<td id="r1c1"></td>
<td id="r1c2"></td>
<td id="r1c3"></td>
<td id="r1c4"></td>
</tr>
<tr>
<td id="r2c1"></td>
<td id="r2c2"></td>
<td id="r2c3"></td>
<td id="r2c4"></td>
</tr>
<tr>
<td id="r3c1"></td>
<td id="r3c2"></td>
<td id="r3c3"></td>
<td id="r3c4"></td>
</tr>
<tr>
<td id="r4c1"></td>
<td id="r4c2"></td>
<td id="r4c3"></td>
<td id="r4c4"></td>
</tr>
<tr>
<td id="r5c1"></td>
<td id="r5c2"></td>
<td id="r5c3"></td>
<td id="r5c4"></td>
</tr>
<tr>
<td id="r6c1"></td>
<td id="r6c2"></td>
<td id="r6c3"></td>
<td id="r6c4"></td>
</tr>
<tr>
<td id="r7c1"></td>
<td id="r7c2"></td>
<td id="r7c3"></td>
<td id="r7c4"></td>
</tr>
<tr>
<td id="r8c1"></td>
<td id="r8c2"></td>
<td id="r8c3"></td>
<td id="r8c4"></td>
</tr>
<tr>
<td><input type="button" onclick="testSort(1);" value="Sort"></td>
<td><input type="button" onclick="testSort(2);" value="Sort"></td>
</tr>
</table>
<script>
function testSort(orderCol) {
orderList = [orderCol];
dataArr = do2DArraySort(dataArr, orderList, 'desc');
for (x=1; x<=numRows; x++) {
document.getElementById('r' + x + 'c3').innerHTML = dataArr[x-1][1];
document.getElementById('r' + x + 'c4').innerHTML = dataArr[x-1][2];
}
}
function TwoDimensionalArray(iRows, iCols) {
var i;
var j;
var a = new Array(iRows);
for (i=0; i < iRows; i++) {
a[i] = new Array(iCols);
for (j=0; j < iCols; j++) {
a[i][j] = "";
}
}
return(a);
}
function do2DArraySort(dataArr, orderList, orderDir) {
//Loop over each item in the list of sort columns. For each one invoke the sort method on the array using the appropriate function.
for (x=orderList.length-1; x >= 0; x--) {
if (orderDir[x] == 'asc') {
dataArr.sort(sortMethodFunctionAsc);
} else {
dataArr.sort(sortMethodFunctionDesc);
}
}
return dataArr;
}
function checkSortValues(a, b) {
var dataType = 'Text';
if ((IsNumeric(a) && IsNumeric(b)) || (a == null && IsNumeric(b)) || (IsNumeric(a) && b == null)) {
dataType = 'Numeric';
}
if ((IsDate(a) && IsDate(b)) || (a == null && IsDate(b)) || (IsDate(a) && b == null)) {
dataType = 'Date';
}
return dataType;
}
function sortMethodFunctionAsc(a, b) {
if (checkSortValues(a[orderList[x]], b[orderList[x]]) == 'Numeric') {
//If the values are numeric, simply check which is larger than the other.
return a[orderList[x]] - b[orderList[x]];
} else if (checkSortValues(a[orderList[x]], b[orderList[x]]) == 'Date') {
//If the values are dates they need converted to date objects. 95% of the time this is not necessary as they are already passed in as dates,
//but the conversion is required to catch the few cases when they are not.
var a2 = new Date(a[orderList[x]]);
var b2 = new Date(b[orderList[x]]);
//The getTime method is used to convert the dates into millisecond ticker equivalents for easier comparison.
return a2.getTime() - b2.getTime();
} else {
//If one of the values is a string, convert both to a string and compare alphabetically.
if (a[orderList[x]].toString() > b[orderList[x]].toString()) {
return 1;
} else if (a[orderList[x]].toString() < b[orderList[x]].toString()) {
return -1;
} else {
//If they are the same, tell the sort to skip them.
return 0;
}
}
}
function sortMethodFunctionDesc(a, b) {
//This function is identical to the ascending one, but the comparison operators are reversed.
if (checkSortValues(a[orderList[x]], b[orderList[x]]) == 'Numeric') {
return b[orderList[x]] - a[orderList[x]];
} else if (checkSortValues(a[orderList[x]], b[orderList[x]]) == 'Date') {
var a2 = new Date(a[orderList[x]]);
var b2 = new Date(b[orderList[x]]);
return b2.getTime() - a2.getTime();
} else {
if (a[orderList[x]].toString() < b[orderList[x]].toString()) {
return 1;
} else if (a[orderList[x]].toString() > b[orderList[x]].toString()) {
return -1;
} else {
return 0;
}
}
}
function IsNumeric(input) {
return (input - 0) == input && input.length > 0;
}
function IsDate(testValue) {
var returnValue = false;
var testDate;
try {
testDate = new Date(testValue);
if (!isNaN(testDate)) {
returnValue = true;
} else {
returnValue = false;
}
}
catch (e) {
returnValue = false;
}
return returnValue;
}
numRows = 8;
orderList = [1];
dataArr = TwoDimensionalArray(numRows, 2);
dataArr[0][1] = 'Jimbo';
dataArr[0][2] = 3;
dataArr[1][1] = 'Jim';
dataArr[1][2] = 0.65;
dataArr[2][1] = 'Jackie';
dataArr[2][2] = 1.25;
dataArr[3][1] = 'John';
dataArr[3][2] = 0.8;
dataArr[4][1] = 'Jacob';
dataArr[4][2] = 0.95;
dataArr[5][1] = 'Jill';
dataArr[5][2] = 0.85;
dataArr[6][1] = 'Jan';
dataArr[6][2] = 0.8;
dataArr[7][1] = 'Jamie';
dataArr[7][2] = 1.45;
for (x=1; x<=numRows; x++) {
document.getElementById('r' + x + 'c1').innerHTML = dataArr[x-1][1];
document.getElementById('r' + x + 'c2').innerHTML = dataArr[x-1][2];
}
</script>
Если вы откроете это в браузере, вы увидите HTML-таблицу, которая выплевывает каждый из столбцов массива в том порядке, в котором они были введены (т. Е. Случайным образом). Если вы нажмете одну из кнопок внизу столбца, она отсортирует данные и поместит их в 3-й и 4-й столбцы. Мое настоящее приложение стирает и перезагружает таблицу, но это работает в демонстрационных целях.
Щелчок по кнопке сортировки внизу текстового столбца работает нормально; сортирует массив по именам в алфавитном порядке. Однако, если вы отсортируете столбец чисел, вы увидите изменение в порядке, но отнюдь не корректное. Результаты одинаковы каждый раз, но отличаются, если щелкнуть сортировку чисел сразу или после текстового поиска (поскольку поиск основан на текущем состоянии массива, а не на исходном массиве). Это именно то, что я вижу в моей заявке.
Мне потребовалось некоторое время, чтобы сузить его, но вот что я определил:
1) Сортировка текста, даты и целых чисел; только десятичные дроби нет.
2) Десятичные дроби сортируются по первой цифре, но игнорируют данные после десятичной запятой.
3) Сортировка по нескольким столбцам работает нормально, но показывает ту же аномалию, поэтому я упростил ее до сортировки по одному столбцу для этого примера.
Я смотрел на это часами, но без удачи, и мог бы использовать свежий взгляд. Почему моя функция array.sort работает неправильно? Любые мысли будут оценены.