Search code examples
javascriptundefinedquicksortcomparatorlogical-operators

Cannot read property of undefined in comparator function


I have a quicksort algoritm (Hoare Partition Scheme) for objects of my class and three comparators.

class Participant {
    login;
    fine;
    solved;
}

/*This function should convert array of strings - 
      ['alla 4 100','gena 6 1000','gosha 2 90','rita 2 90','timofey 4 80']
      Into an array of Participant objects and return their names separated by '\n'
      In this format:
      gena
      timofey
      alla
      gosha
      rita
*/
function effectiveSort(membersInfo) {
    var sortedMembers = [];
    for (let i = 0; i < membersInfo.length; ++i) {
        sortedMembers.push(new Participant);


        sortedMembers[i].login = membersInfo[i].split(' ')[0];
        sortedMembers[i].fine = Number(membersInfo[i].split(' ')[2]);
        sortedMembers[i].solved = Number(membersInfo[i].split(' ')[1]);
    }
    sortedMembers = (quickSort(sortedMembers, 0, sortedMembers.length - 1, loginComparator));
    sortedMembers = (quickSort(sortedMembers, 0, sortedMembers.length - 1, fineComparator));
    sortedMembers = (quickSort(sortedMembers, 0, sortedMembers.length - 1, tasksAmountComparator));

    return sortedMembers.map(a => a.login).join('\n');
}

//Comparators for each class field. That's where the problem starts

function loginComparator(firstParticipant, secondParticipant) {
    return firstParticipant.login < secondParticipant.login;
}

function tasksAmountComparator(firstParticipant, secondParticipant) {
    return firstParticipant.solved >= secondParticipant.solved;
}

function fineComparator(firstParticipant, secondParticipant) {

    return firstParticipant.fine >= secondParticipant.fine;
}

//Hoare Partition Scheme

function partition(arr, start, end, compar) {
    const pivotVal = arr[Math.floor((start + end) / 2)];
    while (start <= end) {
        while (compar(arr[start], pivotVal)) {
            start++;
        }
        while (compar(pivotVal, arr[end])) {
            end--;
        }
        if (start <= end) {
            let temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
            start++;
            end--;
        }
    }
    return start;
}

function quickSort(arr, start = 0, end = arr.length - 1, compar) {
    if (start < end) {
        const index = partition(arr, start, end, compar);
        quickSort(arr, start, index - 1, compar);
        quickSort(arr, index, end, compar);
    }
    return arr;
}

//Test data
var real_mebmers = ['alla 4 100', 'gena 6 1000', 'gosha 2 90', 'rita 2 90', 'timofey 4 80'];
var zero_members = ['alla 0 0', 'gena 0 0', 'gosha 0 0', 'rita 0 0', 'timofey 0 0'];
console.log(effectiveSort(real_mebmers));

The problem starts in these comparators return (firstParticipant.solved >= secondParticipant.solved); and return firstParticipant.fine >= secondParticipant.fine; JS says that.

return (firstParticipant.solved >= secondParticipant.solved); ^ TypeError: Cannot read property 'solved' of undefined

Same goes for fineComparator. If I change these return statements to
return (firstParticipant.solved > secondParticipant.solved); and here return firstParticipant.fine > secondParticipant.fine; Everthing seems fine. But why I can't check two properties for equality? I checked these properties and they don't have 'undefined' value, but JS somehow sees it...


Solution

  • I think you need to do this:

    while (end >= 0 && compar(pivotVal, arr[end])) {
    

    I debugged your code and it looks like when it iterates the end variable can become -1.

    list = [1,2,3];
    console.log(list[0]); does work
    // console.log(list[-1]); // does not work