Почему эта сортировка вставки не может сортировать массивы объектов? (но могут другие значения)

1

Я сделал этот алгоритм сортировки вставки, и он отлично работает с числами/строками, если вы удаляете .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'}] */
  • 1
    Вы читаете за концом массива. Вы пропускаете состояние остановки во внутреннем цикле.
Теги:
arrays
sorting
insertion-sort

1 ответ

1
Лучший ответ

Ваша проблема в этой строке:

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);
  • 1
    Это работает, хотя я лично рекомендовал бы делать правильную проверку границ вместо создания аварийной штриховки для использования недопустимых индексов.
  • 0
    Хорошо, я попытался правильно установить границы с помощью (key <= len-1) && (output[key].name > output[key+1].name) (скобки чисто визуальные, проверка на разделение 2 в моей голове). Хотя, из-за && , я предполагаю, что он по-прежнему запускает .name на выходе, поэтому выбрасывает undefined. Этот key <= len-1 может быть неправильным, хотя, если вы не возражаете, не могли бы вы рассказать, как вы будете применять границы в этом случае.
Показать ещё 2 комментария

Ещё вопросы

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