0

I have the following code( function named group) which groups people objects from persons array into arrays by a certain property(belonging to person object) inside an associative array. So groups(arrays) of people are placed into the resulting associative array by a key that is the property value. For example we have an array that is created and stored into the final array by lastname='Bunny': all the four people from persons with last name Bunny. The problem is that when I do a for in loop trying to display the objects I have at the end of every group an undefined object. This does not happen if I go through the array/object with a for loop. But I can not do it with the associative array since it does not have indexes. I wanted to know why does console.log display an undefined value, can it do something with the prototype? Thanks.

                persons=[
                    { firstname: 'Funny', lastname: 'Bunny', age: 32 },
                    { firstname: 'Little', lastname: 'Bunny', age: 12 },
                    { firstname: 'Buggs', lastname: 'Bunny', age: 42 },
                    { firstname: 'Ivan', lastname: 'Petrov', age: 52 },
                    { firstname: 'Honey', lastname: 'Bunny', age: 22 },
                    { firstname: 'John', lastname: 'Doe', age: 32 },
                    { firstname: 'Mike', lastname: 'Doe', age: 22 }
                ];

                function group(personsArray, groupType) {
                    var associativeArray = {};
                    for (var i in personsArray) {
                        if (!associativeArray[personsArray[i][groupType]]) {
                            associativeArray[personsArray[i][groupType]] = [];
                        }
                        associativeArray[personsArray[i][groupType]].push(personsArray[i]);
                    }
                    return associativeArray;
                }
                var res = group(persons, 'lastname');
                for (var item in res) {
                    console.log('GROUP: ' + item);
                    for (var i = 0; i < res[item].length; i++) {
                        console.log((res[item])[i].firstname);
                    }
                }

                Output:
                        GROUP: Bunny
                        Funny
                        Little
                        Buggs
                        Honey
                        GROUP: Petrov
                        Ivan
                        GROUP: Doe
                        John
                        Mike
                        GROUP: undefined
                        undefined
Petar Drianov
  • 120
  • 2
  • 13
  • 2
    This is probably because of the trailing comma in persons. – adv12 May 17 '14 at 15:25
  • 1
    Don't iterate over real arrays with `for ... in` - the "persons" array should be traversed with a numeric index variable or with a `.forEach()` call. And adv12 is correct - that last trailing comma will (in some browsers; maybe only IE) be interpreted as meaning that you want an extra empty array entry. – Pointy May 17 '14 at 15:27
  • It is not because of the trailing comma in my case which I edited, thanks. I wanted to know why do we not iterate with a for in loop over the array and where does the undefined come from. – Petar Drianov May 17 '14 at 15:40
  • Without that last comma, you don't get `undefined` (or, at least, I certainly don't). [jsfiddle](http://jsfiddle.net/88Zv9/) – Pointy May 17 '14 at 15:41
  • 1
    Even with the trailing you would not get `undefined`. A trailing comma **does not** create an empty entry in the array, it's simply ignored. – Felix Kling May 17 '14 at 15:43
  • The `for ... in` loop is for iterating through the properties of an object. It works with arrays because arrays are objects, but it's a risky practice because arrays can *also* have non-numeric properties. By using a numeric index variable in a simple `for` loop you guarantee that you only involve the numerically indexed properties, and you traverse them in the precise order you want. – Pointy May 17 '14 at 15:43
  • @FelixKling in IE? Sure? *edit* ha ha well me neither but I think at least IE8, maybe IE9 did that. – Pointy May 17 '14 at 15:44
  • @Pointy: I don't care about IE :P *edit:* Yeah, you are probably right. However, the comments made it sound like trailing commas are a problem in general, which they are not. It's only a bug in IE. *edit2:* And I just noticed that I didn't read the second comment, which was also yours ;) – Felix Kling May 17 '14 at 15:44
  • 1
    Maybe you have other code that extends Arrays, in which case `for..in` would also iterate over that extension. Use a `for` loop instead. – Felix Kling May 17 '14 at 15:45
  • Thank you Felix and Pointy for your help, it was an extension that I added to the prototype. And while I was debugging somehow when I pasted the code directly into another browser it still produced undefined. My Webstorm was linked to Chrome and I pasted it in Firefox while debugging in Chrome and it gave me the undefined. When I stopped debugging in Webstorm undefined was gone?? – Petar Drianov May 17 '14 at 16:05

1 Answers1

2

Read Why is using "for...in" with array iteration a bad idea?. If you have any other enumerable properties on your persons array - e.g. inherited from the Array.prototype, then it will also group their lastNames, which are undefined.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375