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)
    ...
5
  • (row['location'] == 'london' is case sensitive and your value is London Commented May 21, 2020 at 9: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 :). Commented May 21, 2020 at 9:06
  • use the next available key that's what .push() does - pushedArray[i].push(singleData[n]) Commented May 21, 2020 at 9: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. Commented May 21, 2020 at 9:50
  • I see what you mean by "inserts all rows in one" with a simple .push: jsfiddle.net/5ezL10y9/1 - need to create the sub-array first and then push to that (2nd dimension), not the 1st dimension Commented May 21, 2020 at 10:18

2 Answers 2

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)

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

Comments

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)

1 Comment

Thanks for this answer. I'll save this for further projects.

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.