3

I would like to sort a JSON items using Javascript by an other array, and to sort the rest of the items in alphabetically please.

I have an array of the order I want to get the JSON items:

var order = [3,9,50,7];

And a JSON with an "ID" key that I want to sort using the order array, and the rest of the non-matching items using the "Name" key please.

Here's the original JSON:

var data = [
    {
        "id": "9",
        "title": "B"
    },
    {
        "id": "63",
        "title": "Z"
    },
    {
        "id": "433",
        "title": "D"
    },
    {
        "id": "50",
        "title": "A"
    },
    {
        "id": "2",
        "title": "G"
    }
]

And this is the end result I want it to be like:

var data = [
    {
        "id": "9",
        "title": "B"
    },
    {
        "id": "50",
        "title": "A"
    },
    {
        "id": "433",
        "title": "D"
    },
    {
        "id": "2",
        "title": "G"
    },
    {
        "id": "63",
        "title": "Z"
    }
]

5 Answers 5

3

You could use an object for the sort order and a default value to move other id to the end.

var order = [3, 9, 50, 7],
    data = [{ id: "9", title: "B" }, { id: "63", title: "Z" }, { id: "433", title: "D" }, { id: "50", title: "A" }, { id: "2", title: "G" }],
    orderO = {};

order.forEach(function (a, i, aa) {
    orderO[a] = i - aa.length; // use negative values and zero as default
});

data.sort(function (a, b) {
    return (orderO[a.id] || 0) - (orderO[b.id] || 0) || a.title.localeCompare(b.title);
});

console.log(data);
console.log(orderO);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much Nina, seems to works good! :) I'm also checking the other answers provided here to see which one is the most efficient.
1

First find the items in your data array that match your order array. Then sort the remaining items using a custom sorting algorithm, concatenate the results.

var order = [3, 9, 50, 7];
var data = [{ "id": "9", "title": "B" }, { "id": "63", "title": "Z" }, { "id": "433", "title": "D" }, { "id": "50", "title": "A" }, { "id": "2", "title": "G" }];

function sortArr(arr, order) {
    var newArr = [];
    for (var i = 0; i < order.length; i++) {
        var index = arr.findIndex(x => x.id === order[i].toString());
        if (index >= 0) {
            newArr.push(arr.splice(index, 1));
        }
    }

    return newArr.concat(arr.sort((a, b) => a.title > b.title ? 1 : -1));
}
console.log(sortArr(data, order));

Comments

1

You can first reduce your order array to one object where key is element and value is index in array. Then use sort to first sort by element that are in array, then sort them by their position in array and finally sort other elements by title.

var data = [{"id":"9","title":"B"},{"id":"63","title":"Z"},{"id":"433","title":"D"},{"id":"50","title":"A"},{"id":"2","title":"G"}]

var order = [3,9,50,7].reduce(function(r, e, i) {
 return r[e] = i, r
}, {})

var result = data.sort(function(a, b) {
 return ((order[b.id] != undefined) - (order[a.id] != undefined) || (order[a.id] - order[b.id])) ||
  	a.title.localeCompare(b.title)
})

console.log(result)

Comments

0

Try this:

var order = [3,9,50,7];
var data = [
    {
        "id": "9",
        "title": "B"
    },
    {
        "id": "63",
        "title": "Z"
    },
    {
        "id": "433",
        "title": "D"
    },
    {
        "id": "50",
        "title": "A"
    },
    {
        "id": "2",
        "title": "G"
    }
]
     let sortedArray =  data.sort((a, b) => {
          return ((order.indexOf(a.id) || Number.Max_VALUE) - (order.indexOf(b.id) || Number.MAX_VALUE) || a.title.localeCompare(b.title) )
        })
      console.log(sortedArray)

1 Comment

how does this sort items with ids in order to the head of the list?
0

Can be done in one sort function. Use Array.indexOf to get a value to sort id in the order array. If only one item is in the order array it is always moved up. All other cases are sorted alphabetically.

var order = [3,9,50,7];

var data = [
    {id: "9", title: "B"},
    {id: "63", title: "Z"},
    {id: "433", title: "D"},
    {id: "50", title: "A"},
    {id: "2",title: "G"},
    {id: "9",title: "F"},
    {id: "7",title: "D"},
    {id: "3",title: "E"},
    {id: "2",title: "F"},
]
// the sort function 
function sortFunc(a,b){
    var iA = order.indexOf(Number(a.id))+1; // get index of A
    var iB = order.indexOf(Number(b.id))+1; // get index of B
    if(iA && iB){  // if both in the order array
        return iA === iB ? // if the same in order array then sort alphabet
            a.title.localeCompare(b.title) :
            iA - iB;
    }
    // if A or B in order array move up else sort alphabet
    return iA ? -1 : iB ? 1 : a.title.localeCompare(b.title);
}
// sort data
data.sort(sortFunc);
// dispay result
data.forEach(obj=>console.log(obj.id + ":" + obj.title))

Comments

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.