2

I have a 2d array with up to [32][32] entries. And I'd like to convert it from something like this:

[
    null, 
    null, 
    null, 
    null, 
    null, 
    null, 
    [null, null, null, null, null, null, null, null, null, null, "player1"],
    [null, null, null, null, null, "player2"]
]

to

{
  "6": {"10":"player1"},
  "7": {"5":"player2"}
}

So this would be my array:

var gameField = [];
gameField[6] = [];
gameField[6][10] = "player1";
gameField[7] = [];
gameField[7][5] = "player2";

Now I tried to use this:

var obj = {}
obj = Object.assign({},gameField);
console.log(JSON.stringify(obj));

but it only worked for the outer array, the inner arrays were not affected:

{
    "6": [null, null, null, null, null, null, null, null, null, null, "player1"],
    "7": [null, null, null, null, null, "player2"]
}

What would be the shortest way to do this properly?

7
  • Can you explain what you are trying to achieve? Commented Jul 25, 2016 at 12:12
  • 1
    This seems like a very bad structure, before and after. Dynamic object keys are mostly hard to use. Why don't you use something cleaner like for example [ {player:'player1', numberOfX:10}, {player:'player2', numberOfX:5} ]. Commented Jul 25, 2016 at 12:13
  • The structure is a bit more complicated in reality. There is more than just players. What I want to achive is to simply convert a 2d array into an object that uses the array indexes as keys. So that I can get rid of all the null values of the array. Commented Jul 25, 2016 at 12:15
  • technically it is [10] would be index = 11 Commented Jul 25, 2016 at 12:15
  • @Forivin If your structure is even more complicated, my point is even more appropriate. Commented Jul 25, 2016 at 12:17

3 Answers 3

6

You can iterate over the items in the array and then recurse if the located item is itself an array (check using Array.isArray)

function populateFromArray(array) {
  var output = {};
  array.forEach(function(item, index) {
    if (!item) return;
    if (Array.isArray(item)) {
      output[index] = populateFromArray(item);
    } else {
      output[index] = item;
    }
  });
  return output;
}

console.log(populateFromArray(input));

This results in:

[object Object] {
  6: [object Object] {
    10: "player1"
  },
  7: [object Object] {
    5: "player2"
  }
}

See a working jsBin

Note: you can certainly do this in less code but less code is not always better!

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

3 Comments

Nice, it works. Can you elaborate a bit on the "less code" thingy?
If you see the answer from @redu then you have a perfect example. This is much less code but - in my opinion - is much harder to understand.
The good thing about your code is that is doesn't break if you place objects instead of strings in the original array.
3

Array.prototype.reduce() seems ideal for this. You may do as follows;

var dataArr = [null,null,null,null,null,null,[null,null,null,null,null,null,null,null,null,null,"Player1"],[null,null,null,null,null,"player2"]],
    dataObj = dataArr.reduce((p,c,i) => (Array.isArray(c) && (p[i] = {[c.length-1]:c[c.length-1]}),p),{});
console.log(dataObj);

2 Comments

Though if I use an object like {id:0,name:'Player1'} instead of "player1", I cannot access the property anymore after the conversion.
@Forivin... Sorry there was an extra set of brackets that i overlooked which was resulting an array ["player1"] instead of a string "player1". Now it should be ok.
1

You could use this recursive function, using ES6 code:

var data = [null,null,null,null,null,null,[null,null,null,null,null,null,null,null,null,null,"player1"],[null,null,null,null,null,"player2"]];

function convert(data) {
    return Array.isArray(data)
        ? data.reduce( (obj, el, i) => (el && (obj[i] = convert(el)), obj), {} )
        : data;
}

var obj = convert(data);

console.log(obj);

This will also work when your input array is nested deeper than 2 levels. It does not require the non-null elements to be at the end of their (sub-)array, nor that there is only one non-null element per (sub-)array.

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.