Я сделал этот алгоритм сортировки вставки, и он отлично работает с числами/строками, если вы удаляете .name
во втором цикле. Хотя я не могу заставить его работать с массивом объекта? (Я даже пробовал несколько проверок стола, и я все еще не могу понять проблему...)
function insertSortByName(d) {
const len = d.length - 1;
let output = d;
for(let sorted = len; sorted >= 0; sorted--) {
for(let key = sorted-1; output[key].name > output[key+1].name; key++) {
output = swapArrayVal(output, key, key+1);
}
}
return output;
}
function swapArrayVal(arr, pos1, pos2) {
let tempVal = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = tempVal;
return arr;
}
Это можно было бы запустить с примером массива как такового:
insertSortByName([ {name: 'z'}, {name: 'm'}, {name: 'a'} ]);
/* Should return: [ {name: 'a'}, {name: 'm'}, {name: 'z'}] */
Ваша проблема в этой строке:
for(let key = sorted-1; output[key].name > output[key+1].name; key++) {
Измените его на:
for(let key=sorted-1; !!output[key+1] && !!output[key] &&
output[key].name>output[key+1].name; key++) {
function insertSortByName(d) {
const len = d.length - 1;
let output = d;
for(let sorted = len; sorted >= 0; sorted--) {
for(let key = sorted-1; !!output[key+1] && !!output[key] && output[key].name > output[key+1].name; key++) {
output = swapArrayVal(output, key, key+1);
}
}
return output;
}
function swapArrayVal(arr, pos1, pos2) {
let tempVal = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = tempVal;
return arr;
}
var retVal = insertSortByName([ {name: 'z'}, {name: 'm'}, {name: 'a'} ]);
console.log(retVal);
Другая реализация может быть основана на алгоритме, доступном в википедии:
i ← 1
while i < length(A)
j ← i
while j > 0 and A[j-1] > A[j]
swap A[j] and A[j-1]
j ← j - 1
end while
i ← i + 1
end while
В следующем фрагменте, который я изменил с помощью, для создания чего-то похожего на ваш подход:
function insertSortByName(arr) {
for(var i=1; i<arr.length;) {
for(var j=i; j>0 && arr[j-1].name > arr[j].name;) {
var tempVal = arr[j];
arr[j] = arr[j-1];
arr[j-1] = tempVal;
j -= 1;
}
i += 1;
}
return arr;
}
var retVal = insertSortByName([ {name: 'z'}, {name: 'm'}, {name: 'a'} ]);
console.log(retVal);
Предыдущий код можно улучшить, добавив обратный вызов сравнения, например, для сортировки. Таким образом, вы можете продолжать использовать ту же функцию для разных объектов.
function insertSort(arr, compareCallBack) {
for(var i=1; i<arr.length;) {
for(var j=i; j>0 && compareCallBack(arr[j-1], arr[j]);) {
var tempVal = arr[j];
arr[j] = arr[j-1];
arr[j-1] = tempVal;
j -= 1;
}
i += 1;
}
return arr;
}
var retVal = insertSort([ {name: 'z'}, {name: 'm'}, {name: 'a'}, {name: 'b'} ], (a, b) => {return a.name > b.name;});
console.log('insertSort with objects: ' + JSON.stringify(retVal));
retVal = insertSort([ 'z', 'm', 'a', 'b'], (a, b) => {return a.localeCompare(b) > 0;});
console.log('insertSort with letters: ' + retVal);
retVal = insertSort([ 10, 7, 8, 1 ], (a, b) => {return a > b;});
console.log('insertSort with numbers: ' + retVal);
(key <= len-1) && (output[key].name > output[key+1].name)
(скобки чисто визуальные, проверка на разделение 2 в моей голове). Хотя, из-за &&
, я предполагаю, что он по-прежнему запускает .name
на выходе, поэтому выбрасывает undefined. Этот key <= len-1
может быть неправильным, хотя, если вы не возражаете, не могли бы вы рассказать, как вы будете применять границы в этом случае.