3

I have the following array:

        [{"cod_nivel":"INC2","cod_modelo":"D"},   
        {"cod_nivel":"PRIM1","cod_modelo":"B"},   
        {"cod_nivel":"INC2","cod_modelo":"B"},  
        {"cod_nivel":"INC1","cod_modelo":"D"},
        {"cod_nivel":"PRIM1","cod_modelo":"D"},
        {"cod_nivel":"BAC2","cod_modelo":"B"},    
        {"cod_nivel":"BAC2","cod_modelo":"D"},    
        {"cod_nivel":"BAC2","cod_modelo":"A"}]

I need to order this array of objects by "cod_modelo" ascending grouped by "cod_nivel". So the result should be:

    [{"cod_nivel":"INC1","cod_modelo":"D"},    
    {"cod_nivel":"INC2","cod_modelo":"B"},
    {"cod_nivel":"INC2","cod_modelo":"D"},    
    {"cod_nivel":"PRIM1","cod_modelo":"B"},    
    {"cod_nivel":"PRIM1","cod_modelo":"D"},
    {"cod_nivel":"BAC2","cod_modelo":"A"},    
    {"cod_nivel":"BAC2","cod_modelo":"B"},    
    {"cod_nivel":"BAC2","cod_modelo":"D"}]

Ok I made this code that orders the array first by cod_nivel and then by cod_modelo:

var sortedArray = array.sort(function (a, b) {
    return (a["cod_nivel"] > b["cod_nivel"]) ? 1 : -1;
}).sort(function (a, b) {
    if (a["cod_nivel"] == b["cod_nivel"])
        return (a["cod_modelo"] > b["cod_modelo"]) ? 1 : -1;
    else
        return 0;
});

The thing is that this code is ordering also by "cod_nivel" so the obtained array would be:

    [{"cod_nivel":"BAC2","cod_modelo":"A"},    
    {"cod_nivel":"BAC2","cod_modelo":"B"},    
    {"cod_nivel":"BAC2","cod_modelo":"D"},
    {"cod_nivel":"INC1","cod_modelo":"D"},    
    {"cod_nivel":"INC2","cod_modelo":"B"},
    {"cod_nivel":"INC2","cod_modelo":"D"},    
    {"cod_nivel":"PRIM1","cod_modelo":"B"},    
    {"cod_nivel":"PRIM1","cod_modelo":"D"}]

Note that BAC2 cod_nivel objects are at the beginning.

What I need is to order first by cod_nivel but in a given order, which is:

  1. INC1
  2. INC2
  3. PRIM1
  4. PRIM2
  5. BAC1
  6. BAC2

I assume I need an array with the fixed order of "cod_nivel" and use it while ordring but I don't know how to use it so I did not include in my approach.

var order_arr = ['INC1', 'INC2', 'PRIM1', 'PRIM2', 'BAC1', 'BAC2']

And after that, order then by cod_modelo (grouped by each cod_nivel).

I hope I have explained myself clearly and someone can help me.

4
  • possible duplicate of Javascript sort function. Sort by First then by Second Commented Apr 13, 2015 at 9:20
  • Put your sorting code in one callback: First compare the code_nivel properties and just, if those are the same sort by cod_modelo. Commented Apr 13, 2015 at 9:20
  • Did you try underscorejs.org , it's really easy to do such stuff with Underscore.js Commented Apr 13, 2015 at 9:21
  • Possible duplicate of Sort array of objects in specific order Commented Nov 20, 2015 at 14:40

2 Answers 2

10

You can assign indexes in an associative array, like this

var cod_nivel_order = {
    'INC1': 0,
    'INC2': 1,
    'PRIM1': 2,
    'PRIM2': 3,
    'BAC1': 4,
    'BAC2': 5
};

and then you can sort like this

function compare(a, b) {
    if (a === b) {
        return 0;
    }
    return a < b ? -1 : 1;
}

var sortedArray = array.sort(function (a, b) {

    // First compare corresponding values of `cod_nivel` from `cod_nivel_order`
    var index_result = compare(cod_nivel_order[a.cod_nivel],
        cod_nivel_order[b.cod_nivel]);

    // If they are equal
    if (index_result === 0) {

        // Return the result of comparing `cod_modelo`s
        return compare(a.cod_modelo, b.cod_modelo);
    }

    return index_result;
});

and now the result will be

[ { cod_nivel: 'INC1', cod_modelo: 'D' },
  { cod_nivel: 'INC2', cod_modelo: 'B' },
  { cod_nivel: 'INC2', cod_modelo: 'D' },
  { cod_nivel: 'PRIM1', cod_modelo: 'B' },
  { cod_nivel: 'PRIM1', cod_modelo: 'D' },
  { cod_nivel: 'BAC2', cod_modelo: 'A' },
  { cod_nivel: 'BAC2', cod_modelo: 'B' },
  { cod_nivel: 'BAC2', cod_modelo: 'D' } ]
Sign up to request clarification or add additional context in comments.

11 Comments

but this is not ordering the cod_modelos specifically with the order I need, isn't it? 1. INC1 2. INC2 3. PRIM1 4. PRIM2 5. BAC1 6. BAC2
@Egidi That is exactly the point. You don't have to sort it twice (first by cod_modelo and then by cod_nivel). It will give you the expected result. I explained the rules of comparison also. Please check.
I am testing it and it is not giving the nedeed result. I can understand that i don't need to sort it twice, but as told, I need to be in the array first the objects "cod_nivel"='INC1' then 'INC2' objects then 'PRIM1'...with your code is ordering 'BAC1' objects at the beginning of the array because it is ordering by cod_nivel ascending and BAC1 is before INC1... am i wrong?
@Egidi I don't see a pattern in your sorting. When you sort based on cod_modelo first and then cod_nivel then, why D appears after B in the expected result?
Yes, the cod_modelo has to be sorted ascending (a,b,c,d,e,f,g...) but the cod_nivel has to be sorted in a specific way ( 1. INC1 2. INC2 3. PRIM1 4. PRIM2 5. BAC1 6. BAC2)...note that it is not ascening...it's a fixed order. Maybe I haven't explained myself well...I appreciate a lot your help by the way.
|
3
var data = [{
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "PRIM1",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC1",
    "cod_modelo": "D"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "PRIM2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "A"
}];
var sortOrder = ['INC1', 'INC2', 'PRIM1', 'PRIM2', 'BAC1', 'BAC2'];
data.sort(function (a, b) {
    // first have a look at cod_nivel
    // get the indices of the given sortOrder
    // take the difference of the indices
    var delta = sortOrder.indexOf(a.cod_nivel) - sortOrder.indexOf(b.cod_nivel);
    // test, if the indices are the same
    if (delta === 0) {
        // the comparison should usually return 0,
        // but this will here not work. we need
        // the comparison of the second sort order of cod_modelo.
        // take the variables and make a real comparison,
        // while we expecting strings to be compared
        return a.cod_modelo === b.cod_modelo ? 0 : (a.cod_modelo < b.cod_modelo ? -1 : 1);
    }
    // otherwise return the delta
    return delta;
});

as thefortheye mentioned, the former version does not compute very well. so here is the type safe version for number/number or string/string comparison.

2 Comments

Could do with some explanation of what your doing and why.
Note: This will NOT work in all environments as JavaScript's sort is not guaranteed to be stable in all the environments. It is left to the implementations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.