Home > Enterprise >  Sort array by multiple fields but item that has priority field goes first
Sort array by multiple fields but item that has priority field goes first

Time:05-04

I have a small sorting algorithm that sorts an array by multiple fields:

const termKeys = Object.keys(proposal.terms);

const sorted = termKeys.sort((a, b) => {
  if (proposal.terms[a].unified_price === proposal.terms[b].unified_price) {
    return gates[b].productivity - gates[a].productivity;
  }

  return proposal.terms[a].unified_price - proposal.terms[b].unified_price;
});

I want to add an additional optional parameter to this sorting algorithm that would keep the order but put items that has special field first. For example, the followint list:

const proposal = {
  terms: {
    '1': {
      unified_price: 123,
      productivity: 10,
      has_baggage: false,
    },
    '2': {
      unified_price: 111,
      productivity: 10,
      has_baggage: false,
    },
    '3': {
      unified_price: 456,
      productivity: 10,
      has_baggage: true,
    },
    '4': {
      unified_price: 678,
      productivity: 10,
      has_baggage: true,
    }
  }
}

should be in the following order

['3', '4', '2', '1']

I tried adding an additional function and a number to formula but that just didn't affect the order:

const hasBaggage = true;
const proposal = {
  terms: {
    '1': {
      unified_price: 123,
      productivity: 10,
      has_baggage: false,
    },
    '2': {
      unified_price: 111,
      productivity: 10,
      has_baggage: false,
    },
    '3': {
      unified_price: 456,
      productivity: 10,
      has_baggage: true,
    },
    '4': {
      unified_price: 678,
      productivity: 10,
      has_baggage: true,
    }
  }
}

function decidePositionOfBaggage(a, b) {
  if (a === b) {
    return 0;
  }

  if (b === false && a === true) {
    return -1;
  }

  if (b === true && a === false) {
    return 1;
  }
}

function sortProposal(proposal) {
  const termKeys = Object.keys(proposal.terms);

  const sorted = termKeys.sort((a, b) => {
    const hasBaggageNumber = decidePositionOfBaggage(proposal.terms[a].has_baggage, proposal.terms[b].has_baggage);
    
    if (proposal.terms[a].unified_price === proposal.terms[b].unified_price) {
      return (gates[b].productivity - gates[a].productivity) - hasBaggageNumber;
    }
  
    return (proposal.terms[a].unified_price - proposal.terms[b].unified_price) - hasBaggageNumber;
  });

  return sorted;
}

console.log(sortProposal(proposal))

CodePudding user response:

Your code can be massively simplified to this:

const proposal = {
    terms: {
        1: {
            unified_price: 123,
            productivity: 10,
            has_baggage: false,
        },
        2: {
            unified_price: 111,
            productivity: 10,
            has_baggage: false,
        },
        3: {
            unified_price: 456,
            productivity: 10,
            has_baggage: true,
        },
        4: {
            unified_price: 678,
            productivity: 10,
            has_baggage: true,
        },
    },
};

const sort = ({ terms }) => {
    return Object.entries(terms).sort(([_, a], [__, b]) => {
        if (a.has_baggage && !b.has_baggage) return -1;
        if (!a.has_baggage && b.has_baggage) return 1;

        return a.unified_price - b.unified_price;
    });
};

console.log(sort(proposal));

CodePudding user response:

You want to do the sorting like this:

const hasBaggage = true
const proposal = {
  terms: {
    '1': {
      unified_price: 123,
      productivity: 10,
      has_baggage: false,
    },
    '2': {
      unified_price: 111,
      productivity: 10,
      has_baggage: false,
    },
    '3': {
      unified_price: 456,
      productivity: 10,
      has_baggage: true,
    },
    '4': {
      unified_price: 678,
      productivity: 10,
      has_baggage: true,
    }
  }
}

function decidePositionOfBaggage(a, b) {
  if (a === b) {
    return 0;
  }

  if (b === false && a === true) {
    return -1;
  }

  if (b === true && a === false) {
    return 1;
  }
}

function sortProposal(proposal) {
  const termKeys = Object.keys(proposal.terms);

  const sorted = termKeys.sort((a, b) => {
    const hasBaggageNumber = decidePositionOfBaggage(proposal.terms[a].has_baggage, proposal.terms[b].has_baggage);

    if (hasBaggageNumber !== 0) {
      return hasBaggageNumber
    }
    if (proposal.terms[a].unified_price === proposal.terms[b].unified_price) {
      return (gates[b].productivity - gates[a].productivity);
    }

    return (proposal.terms[a].unified_price - proposal.terms[b].unified_price);
  });

  return sorted;
}

console.log(sortProposal(proposal))

The main change is that basically you just need to check first for the property that has priority and check for the others just when the priority is the same between both items

  • Related