1

I'd like to create a multidimensional array using a loop in jQuery/JS. Is it possible to use the next available key instead of setting it manually?

jsonFromPhp contains something like this:

0 {first_name: "Tom", last_name: "Smith", location: "London"}
1 {first_name: "Max", last_name: "Muster", location: "Zurich"}
2 {first_name: "Joanne", last_name: "Kate", location: "London"}
...

Here is the loop:

jsonFromPhp.forEach((row, i) => {
    if (row['location'] == 'London') {
        firstKey = 0;
    } else {
        firstKey = 1;
    }

    row.forEach((singleData, n) => {
        pushedArray[firstKey][] = singleData[n]; // doesn't work, I have set the index manually (with i for example). But then I have an array like 0, 2, 5 etc. and I need 0, 1, 2
    });
});

Expected Result:
0 Array (1)
    0 ["Tom", "Smith", "London"] (3)
    1 ["Joanne", "Kate", "London"] (3)
    ...
1 Array (1)
    0 ["Max", "Muster", "Zurich"] (3)
    ...

and not (if I set pushedArray[firstKey][i])

0 Array (1)
    0 ["Tom", "Smith", "London"] (3)
    2 ["Joanne", "Kate", "London"] (3)
    ...
1 Array (1)
    1 ["Max", "Muster", "Zurich"] (3)
    ...

or

0 Array (1)
    0 ["Tom", "Smith", "London", "Joanne", "Kate", "London"] (6)
1 Array (1)
    1 ["Max", "Muster", "Zurich"] (3)
    ...
Mr. Potter
  • 85
  • 7
  • `(row['location'] == 'london'` is case sensitive and your value is `London` – freedomn-m May 21 '20 at 09:04
  • @freedomn-m Thanks for the hint, updated the code. This is just a shorter version of my code so if there are still typing errors, I'm sorry :). – Mr. Potter May 21 '20 at 09:06
  • *use the next available key* that's what `.push()` does - `pushedArray[i].push(singleData[n])` – freedomn-m May 21 '20 at 09:27
  • @freedomn-m But this inserts all rows in one. Take a look at the expected output and what I don't expect/need. :) Basicly I need an head array and a row array with all values. – Mr. Potter May 21 '20 at 09:50
  • I see what you mean by "inserts all rows in one" with a simple .push: https://jsfiddle.net/5ezL10y9/1/ - need to create the sub-array first and then push to that (2nd dimension), not the 1st dimension – freedomn-m May 21 '20 at 10:18

2 Answers2

1

This solution will work for more than 2 locations as well as no need to care about what values come for location from backend.

const arr = [{
  first_name: "Tom",
  last_name: "Smith",
  location: "London"
}, {
  first_name: "Max",
  last_name: "Muster",
  location: "Zurich"
}, {
  first_name: "Joanne",
  last_name: "Kate",
  location: "London"
}]
const result = {};

arr.map(item => {
  result[item.location] = [];
  return item;
}).map(item => {
  result[item.location].push(Object.values(item));
});

let res2 = [];
Object.keys(result).forEach((key, index) => {
  res2[index] = result[key]
});
console.log(res2)
Vaibhav
  • 1,412
  • 1
  • 10
  • 14
1

use the next available key

To generate array indices automatically, the easiest way is with

arr.push(value)

this is the same as

arr[arr.length] = value

The issue in this question is for multi-dimensional array to ensure you are "pushing" into the correct dimension.

In this case, the 1st dimension ("london") is always 2 long, so we can simplify this by creating the array up-front:

var arr = [[],[]];

which creates an array with 2 entries, both of which are themselves empty arrays (2 dimensions).

The code then determines whether to use 0 or 1, that's fine - the next dimension is then for each row / object in the source and under that is where the data goes, giving:

var source = [
{first_name: "Tom", last_name: "Smith", location: "London"},
{first_name: "Max", last_name: "Muster", location: "Zurich"},
{first_name: "Joanne", last_name: "Kate", location: "London"}
];

// create 1st dimension (arr[0], arr[1]) initially
var arr=[[],[]];

// loop through each source row
source.forEach((row, i) => {
    if (row['location'] == 'London') {
        firstKey = 0;
    } else {
        firstKey = 1;
    }
    
    // add a subdimension for this row
    var rowArr = [];
    for(var k in row)
    {
        // add the properties into the subdimension
        rowArr.push(row[k]); 
    }
    
    // add the object->array into the 0/1 top-level array
    // using "the next available index"
    arr[firstKey].push(rowArr);
        
});
console.log(arr);

This can or course be substantially reduced (eg using .map and ?: for location), but this keeps the closest to your original code, changing only the parts relevant to the question.


Reducing your code using .forEach

Using object to array and the same principle of creating the base array up-front you can use ?: to reduce the location index:

firstKey = row['location'] == 'London' ? 0 : 1

We can reduce your code to a one-liner (split for clarity):

var source = [
{first_name: "Tom", last_name: "Smith", location: "London"},
{first_name: "Max", last_name: "Muster", location: "Zurich"},
{first_name: "Joanne", last_name: "Kate", location: "London"}
];

var arr = [[],[]];

source.forEach((row) => 
    arr[row['location'] == 'London' ? 0 : 1].push(
        Object.keys(row).map(
            (key) => row[key]
        )
    )
);

console.log(arr)
freedomn-m
  • 27,664
  • 8
  • 35
  • 57