Reputation:
I'm trying to sort items from an array into another array, but categorised. My code is currently working, but the trouble is that I need to know the size of the "sort" array. At the moment, there are four entries, which works with "data". The first two data.cat are compared to n, and their IDs are pushed into sort[0]. When two do not match, 1 is added to c. The code then loops through again, pushing the new matches into sort[1], etc, etc.
var data = [
{"cat": 0, "id":"AAAA"},
{"cat": 0, "id":"BBBB"},
{"cat": 1, "id":"CCCC"},
{"cat": 1, "id":"DDDD"},
{"cat": 1, "id":"EEEE"},
{"cat": 1, "id":"FFFF"}, //pseudodata
{"cat": 1, "id":"GGGG"},
{"cat": 2, "id":"HHHH"},
{"cat": 2, "id":"IIII"},
{"cat": 2, "id":"JJJJ"},
{"cat": 3, "id":"KKKK"}
];
var sort = [[], [], [], [],]
function sortDates(){
var n = 0;
for (var i = 0; i < data.length; i++){
if (data[i].cat == n){
console.log("Category " + n +" entry: " + data[i].id);
sort[n].push(data[i].id);
} else {
console.log("Entry " + data[i].id + " does not match. Moving to next category...");
n++;
i--;
}
}
}
This all works okay, but if I add more to the data array (such as {"cat": 4, "id":"LLLL"}), the program crashes with "sort[n] is not a function". This is because there are only four available items in the sort array.
So I'm just wondering, is there any way to get around this? If the data array is always changing size, and more entries/categories are added, do I have to keep resizing the sort array manually?
Upvotes: 3
Views: 1188
Reputation: 18515
Another way you can achieve this with ES6 in a more concise manner is to use Array.reduce
and inside Array.sort
via String.localeCompare
:
var data = [{ "cat": 0, "id": "BBBB" }, { "cat": 0, "id": "AAAA" }, { "cat": 1, "id": "CCCC" }, { "cat": 1, "id": "DDDD" }, { "cat": 1, "id": "EEEE" }, { "cat": 1, "id": "FFFF" }, { "cat": 1, "id": "GGGG" }, { "cat": 2, "id": "HHHH" }, { "cat": 2, "id": "IIII" }, { "cat": 2, "id": "JJJJ" }, { "cat": 3, "id": "KKKK" } ]
const result = Object.values(data.reduce((r,c) => {
r[c.cat] = [...r[c.cat] || [], c.id].sort((a,b) => a.localeCompare(b))
return r
}, {}))
console.log(result)
String.localeCompare
has various options in terms of how to compare (like dealing with numbers in the strings, case sensitivity etc)
The idea is to use the Array.reduce
is to group the entries in an object and then just use Object.values
to get the desired output (milti-dimentional array).
Upvotes: 0
Reputation: 386568
You could use a default check of the array with a logical OR ||
and assign an empty array if the item is not set.
sort[n] = sort[n] || [];
sort[n].push(data[i].id);
BTW, you could use cat
directly without iterating sort
array for getting the right index.
function sortDates() {
var i, sort = [];
for (i = 0; i < data.length; i++) {
sort[data[i].cat] = sort[data[i].cat] || [];
sort[data[i].cat].push(data[i].id);
}
return sort;
}
var data = [{ cat: 0, id: "AAAA" }, { cat: 0, id: "BBBB" }, { cat: 1, id: "CCCC" }, { cat: 1, id: "DDDD" }, { cat: 1, id: "EEEE" }, { cat: 1, id: "FFFF" }, { cat: 1, id: "GGGG" }, { cat: 2, id: "HHHH" }, { cat: 2, id: "IIII" }, { cat: 2, id: "JJJJ" }, { cat: 3, id: "KKKK" }],
result = sortDates(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1