user10650826
user10650826

Reputation:

Multidimensional array of an unknown size in JavaScript

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

Answers (2)

Akrion
Akrion

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

Nina Scholz
Nina Scholz

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

Related Questions