skip to Main Content

I am trying to sort an object of strings, which would work with the normal sort function, but I am not able to get it working as the strings start with a number:

e.g.:

{ value: "10 items", value: "5 items", value: "100 items", value: "20 items" }

I want to make it ascending, so it becomes:

5 items
10 items
20 items
100 items

I’ve been trying to use:

data.sort((a, b) => a > b ? 1 : -1).map((a) => { return a;}

But that still shows it as:

10 items
100 items
20 items
5 items

4

Answers


  1. You need to compare the first parts of your strings numerically, so we split them, get the first element, convert them to int and then we can compare it. See below:

    let data = [ "10 items", "5 items", "100 items", "20 items" ];
    data.sort((a, b) => {
        let x = parseInt(a.split(" ")[0]);
        let y = parseInt(b.split(" ")[0]);
        if (x === y) {
            return 0;
        } else {
            return x > y ? 1 : -1;
        }
    });
    console.log(data);

    Note that I have reinterpreted your input, since the one you have given was obviously wrong, as repeating the same key inside an object (value) in this case is invalid.

    Login or Signup to reply.
  2. You can extract the numbers with s.slice(0, s.indexOf(' ') and compare them:

    let data = [ "10 items", "5 items", "100 items", "20 items" ];
    const getNum = s => s.slice(0, s.indexOf(' '));
    data.sort((a, b) => (a = getNum(a), b = getNum(b), a-b));
    console.log(data);

    If you want to speed up you could compare lengths of the numbers first and then compare them char-by-char if the length is equal:

    ` Chrome/124
    -----------------------------------------------------
    Alexander      ■ 1.00x | x1000000 174 183 189 192 197
    Lajos Arpad      1.57x | x1000000 274 286 296 300 306
    Peter Seliger  103.45x |   x10000 180 184 191 204 204
    -----------------------------------------------------
    https://github.com/silentmantra/benchmark `
    
    let data = [ "10 items", "5 items", "100 items", "20 items" ];
    
    // @benchmark Alexander
    data.toSorted((a, b) => {
      a = a.slice(0, a.indexOf(' ')), b = b.slice(0, b.indexOf(' '));
      if(a.length > b.length) return 1;
      if(a.length < b.length) return -1;
      for(let i = 0;i < a.length;i++){
        if(a[i] > b[i]) return 1;
        if(a[i] < b[i]) return -1;
      }
      return 0;
    });
    
    // @benchmark Peter Seliger
    data.toSorted((a, b) => a.localeCompare(b, undefined, { numeric: true }));
    
    // @benchmark Lajos Arpad
    data.toSorted((a, b) => {
        let x = parseInt(a.split(" ")[0]);
        let y = parseInt(b.split(" ")[0]);
        if (x === y) {
            return 0;
        } else {
            return x > y ? 1 : -1;
        }
    });
    
    /*@skip*/ fetch('https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js').then(r => r.text().then(eval));
    Login or Signup to reply.
  3. As @somethinghere mentioned in the comment you can use localeCompare to sort numerical data

    const data = [{ value: "10 items" },
                  { value: "5 items"},
                  {value: "100 items"},
                  {value: "20 items"}
        ];
    const result = data.sort((a, b) => a.value.localeCompare(b.value,undefined,{numeric:true}));
    console.log(result );
    Login or Signup to reply.
  4. console.log(
      Object
        .values({
          value1: "10 items",
          value2: "5 items",
          value3: "100 items",
          value4: "20 items",
          value5: "20 facts",
        })
        .sort((a, b) =>
          a.localeCompare(b, undefined, { numeric: true })
        )
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    And in case the OP wanted to sort an array of equally structured object items, the above solution slightly changes too …

    console.log(
      [{
        value: '10 items',
      }, {
        value: '5 items',
      }, {
        value: '100 items',
      }, {
        value: '20 items',
      }, {
        value: '20 facts',
      }]
      .sort((a, b) =>
        a.value.localeCompare(b.value, undefined, { numeric: true })
      )
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search