Infinite loop while sorting list of array of objec

2019-08-12 03:36发布

问题:

So I'm trying to sort the column by clicking on the header and it causes much damage. I guess it's an infinite loop :)

Though, same logic works fine while it was array of arrays, not objects. It's all in redux reducer.

Where is my bug?

const newData = an array of objects.

newData[0] - {
               show: true,
               value: [5, 3, "quidem molestiae enim"]
             }

newData[0].value - it's a table row with td.

const sortDataFunc = (state, action) => {
        const newData = [].concat(action.data);
        index = action.columnIndex;
        let i, x, y, shouldSwitch, switchcount = 0;
        let switching = true;
        let dir = "asc"; 

        /* Make a loop that will continue until
        no switching has been done: */
        while (switching) {
          switching = false;
          for (i = 0; i < (newData.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 = newData[i].value[index];
            y = newData[i + 1].value[index];  

            /* Check if the two rows should switch place,
            based on the direction, asc or desc: */
            if (dir === "asc") {
              if (x > y) {
                // If so, mark as a switch and break the loop:
                shouldSwitch = true;
                break;
              }
            } else if (dir === "desc") {
              if (x < y) {
                // 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: */
            const newRow = newData[i + 1];
            const copyObj = Object.assign({}, newRow);
            newData.splice(i + 1, 1);
            newData.splice(i, 0, copyObj);
            switching = true;
            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;
            }
          }
        } 
        return {
            ...state,
            dataToTable: newData
        }
};

回答1:

try to use standard js sort and split data and view

let newData = [
  {show: true, value: [5, 1, "quidem molestiae enim"] },
  {show: true, value: [6, 3, "abc"] },
  {show: true, value: [7, 2, "zzz"] },
  {show: false, value: [8, 9, "not show"] },
];

let dir=[1,1,1] // sort direction

function sort(i) {
  if(i<2) newData = newData.sort((a,b)=> dir[i]*(a.value[i]-b.value[i]));
  if(i==2) newData= newData.sort((a,b)=> dir[i]*(a.value[i]<b.value[i]?-1:1));
  dir[i]*=-1
  show();
}

function show() {
  content.innerHTML = newData.map(d=> d.show ? '<tr>'+d.value.map(x=>`<td>${x}</td>`).join('')+'</tr>' : '').join('');
}

show();
thead td { cursor: pointer; border-bottom: 1px solid black; padding: 0 10px 3px 10px}
<div>(click on column name to sort)<br><br></div>
<table >
<thead><tr>
  <td onclick='sort(0)'>ID</td>
  <td onclick='sort(1)'>Age</td>
  <td onclick='sort(2)'>Text</td>
</tr></thead>
<tbody id='content'></tbody>
</table>