Home > Mobile >  Sort function with undefined value
Sort function with undefined value

Time:12-09

I have an array of object like below:

 var stores = [
      {
        "name": "store3",
        "ditance": 8
      },
      {
        "name": "Store5",
        "distance": 7,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isFutureOrderPossible": false
          }
        }
      },
      {
        "name": "Store1",
        "distance": 12,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isOpen": true
          }
        }
      },
      {
        "name": "store2",
        "distance": 13,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isOpen": true
          }
        }
      }
    ]

Expected Result to be sort based on isopen and distance

[
  {
    "name": "Store1",
    "distance": 12,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isOpen": true
      }
    }
  },
  {
    "name": "store2",
    "distance": 13,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isOpen": true
      }
    }
  },
  {
    "name": "Store5",
    "distance": 7,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isFutureOrderPossible": false
      }
    }
  },
  {
    "name": "store3",
    "ditance": 8
  }
]

Need to sort an array based on isOpen and distance .The challenge is some object have web property and some object don't have. Even if web available sometimes isOpen won't their. I have tried the below approch it's not working

const sorter = (a, b) => {
                if (a.web) {
                  if (a.web.validateAttributes) {
                    if (a.web.validateAttributes.isOpen) {
                      return 1;
                    } else if (b.web.validateAttributes.isOpen) {
                      return -1;
                    } else {
                      return 1;
                    };
                  } else {
                    return 1;
                  }
                 
                } else {
                  return 1;
                }
              };
  stores.sort(sorter);

CodePudding user response:

You can use some optional chaining to turn the isOpen properties into a -1 if truthy or 1 if falsy to establish their position.

If those properties are equal, then fallback to a distance comparison.

// fixed "ditance" to "distance" in "store3"
const stores = [{"name":"store3","distance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]

const sorted = [...stores].sort((a, b) => 
  (a.web?.validateAttributes?.isOpen ? -1 : 1) -
  (b.web?.validateAttributes?.isOpen ? -1 : 1) ||
  (a.distance - b.distance))
  
console.log(sorted)
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

I see 2 problems.

  1. typo at the first item "ditance": 8
  2. Your sorting function. Here is my logic. Firstly, check both are Opening or Closing, then compare distance. Else just simple compare the state open/close

var stores = [{"name":"store3","distance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}];
    
stores.sort((a, b) => {
  if (a.web?.validateAttributes?.isOpen && b.web?.validateAttributes?.isOpen || !a.web?.validateAttributes?.isOpen && !b.web?.validateAttributes?.isOpen) {
    return a.distance - b.distance;
  }
  if (a.web?.validateAttributes?.isOpen) {
    return -1;
  }
  return 1;
})

console.log(stores);

CodePudding user response:

Try this.

const stores = [{"name":"store3","ditance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]

const sorted = stores.slice();

sorted.sort((a, b) => {
    if (!a.web || !b.web) {
        return -1;
    }
    if (!a.web.validateAttributes || !b.web.validateAttributes) {
        return -1;
    }
    const x = a.web.validateAttributes.isOpen || false;
    const y = b.web.validateAttributes.isOpen || false;

    return (x === y) ? a.distance - b.distance : -1;
})
console.log(sorted)
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

Try this

const stores = [{"name":"store3","ditance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]

   const sorter = (a,b)=> {
      if(!b.web) {
          return -1;
      }
      else if(!b.web.validateAttributes) {
        return -1;
      }
      else if(!b.web.validateAttributes.isOpen) {
        return -1;
      }
      return (a.distance - b.distance)
   }
   console.log(stores.sort(sorter)) 

CodePudding user response:

After fixing some typos here is another alternative.

If not set, default each isOpen to false and store. If they are the same, sort on distance, otherwise sort on the isOpen.

let stores = [{"name":"Store1","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"Store5","distance":8,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"store3","distance":7}];

function comparator(a,b) {
  let aResult = a?.web?.validateAttributes?.isOpen ?? false;
  let bResult = b?.web?.validateAttributes?.isOpen ?? false;
  return (aResult === bResult)? a.distance - b.distance : bResult - aResult;
}
console.log(stores.sort(comparator));

  • Related