2

I will illustrate what I want to do with a trivial example. Let's say I have a variable rows with the content:

[ { id: 1,
    admin_id: 2,
    start_date: Mon Nov 18 2013 07:19:46 GMT-0800 (PST),
    status: 1,
    username: 'Marko Markovic' },
  { id: 7,
    admin_id: 3,
    start_date: Mon Nov 18 2013 07:20:32 GMT-0800 (PST),
    status: 0,
    username: 'Dzoni Noksvil' } ]

Now, what I want to create is the following:

var gl = { 
        1: { admin: "Marko Markovic" , status: "1" },
        7: { admin: "Dzoni Noksvil" , status: "0" }
    };

So, I need to loop through rows and, for each row, add a row to the gl object according to the rule which i think is clear from the example above.

So I tried this.

var gl;

rows.forEach(function(row) {
    gl[row.id] = { admin: row.username, status: row.status };
});

The above code throws an error saying Cannot set property '1' of undefined. I also tried the following, knowing it won't work but curious as to what error it will throw:

var gl;

rows.forEach(function(row) {
    gl.row.id = { admin: row.username, status: row.status };
});

And the error was Cannot read property 'row' of undefined.

Can someone tell me how to do this correctly and, if possible, the meaning of the errors because I don't know what is supposed to be undefined here.

Oh, and please, plain Javascript only, even if jQuery has an easier/better solution.

1
  • Do you really want "gl" to be a plain object and not an array? You're using numeric keys anyway. Commented Jan 18, 2014 at 15:16

4 Answers 4

3
var gl;

will initialize gl with undefined by default. If you are trying to build an object, you have to initialize it with an object, like this

var gl = {};

Or you can do it with Array.prototype.reduce function, like this

var data = [ { id: 1,
    admin_id: 2,
    start_date: "Mon Nov 18 2013 07:19:46 GMT-0800 (PST)",
    status: 1,
    username: 'Marko Markovic' },
  { id: 7,
    admin_id: 3,
    start_date: "Mon Nov 18 2013 07:20:32 GMT-0800 (PST)",
    status: 0,
    username: 'Dzoni Noksvil' } ];

var result = data.reduce(function(result, currentObject) {
    result[currentObject.id] = {
        admin: currentObject.username,
        status: currentObject.status
    };
    return result;
}, {});

console.log(result);

Output

{ '1': { admin: 'Marko Markovic', status: 1 },
  '7': { admin: 'Dzoni Noksvil', status: 0 } }

Online Demo - It has both, your fixed version and my proposed version.

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

5 Comments

Thanks, but after initializing gl properly as you said, even though there's no error, doing console.log(gl) afterwards just logs {}. Is there anything else wrong with my code?
@jovan if you copied the .reduce() code, it puts the result in a variable called "result".
No, I mean my own code from the question (the first version).
@jovan Can you please create jsfiddle, so that it will be easy to debug?
@jovan Please check this jsfiddle.net/VL8hV. It has both, your fixed version and my proposed version.
2

You forgot to initialize gl so that it had the value undefined when you tried to set a property on it.

var gl = {};
…

Comments

2

You forgot to initialize "gl"

var gl = {};

Also, you could use .reduce instead:

var gl = rows.reduce(function(gl, row) {
  gl[row.id] = { admin: row.username, status: row.status };
  return gl;
}, {});

I don't know what your "id" values may look like, but if you're always using numeric keys anyway, it seems to me that you might as well make "gl" be an array and not just a plain object. That way, you'll be able to use .forEach etc on it.

Note that the native iterator functions skip over "holes" in the arrays over which they operate. That means that in this case, if you started off "gl" as an array, you'd end up with holes for positions 0, 2, 3, 4, 5, and 6, because you only set 1 and 7. The length of the array would be 8, but a call to .forEach() or .map() or whatever would only perform two calls to the callback. That's different from something like jQuery's $.each().

2 Comments

If I do it as an array, would that be by using gl[row.id]['admin']=row.username; gl[row.id]['status']=row.status; etc?
@jovan just initialize it with [] instead of {}. Everything else would be the same.
2

If you need to support older browsers that don't support native Array.prototype.reduce then you can use a regular for loop and new array:

var gl = function () {
  var myArray = [];
  for (var i = 0; i < rows.length; i++) {
      var self = rows[i];
      var obj = {};
      obj[self.id] = {
          admin: self.username,
          status: self.status
      }
      myArray.push(obj);
  }
  return myArray;
};

// output
console.log(gl());

jsFiddle

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.