Search code examples
javascriptarraysobjectfor-loopfor-in-loop

Looping through an object and putting result to an array with javascript


I'm trying to loop through an object, to put some values from the object, into a new array. But I have a really hard time figuring out how to do it.

This is my object:

var vehicles = {
    list:{
        "transport":{ //<-- This is the values I want to put to an array
            name:"transport",
            pixelWidth:31,
            pixelHeight:30,
            pixelOffsetX:15,
            pixelOffsetY:15,
            radius:15,
            speed:15,
            sight:3,
            cost:400,
            hitPoints:100,
            turnSpeed:2,
            spriteImages:[
                {name:"stand",count:1,directions:8}         
            ],
        },
        "harvester":{ //<-- This is the values I want to put to an array
            name:"harvester",
            pixelWidth:21,
            pixelHeight:20,
            pixelOffsetX:10,
            pixelOffsetY:10,
            radius:10,
            speed:10,
            sight:3,
            cost:1600,
            hitPoints:50,
            turnSpeed:2,
            spriteImages:[
                {name:"stand",count:1,directions:8}         
            ],
        },
        "scout-tank":{ //<-- This is the values I want to put to an array
            name:"scout-tank",
            canAttack:true,
            canAttackLand:true,
            canAttackAir:false,
            weaponType:"bullet",
            pixelWidth:21,
            pixelHeight:21,
            pixelOffsetX:10,
            pixelOffsetY:10,
            radius:11,
            speed:20,
            sight:3,
            cost:500,
            hitPoints:50,
            turnSpeed:4,
            spriteImages:[
                {name:"stand",count:1,directions:8}         
            ],
        },
        "heavy-tank":{ //<-- This is the values I want to put to an array
            name:"heavy-tank",
            canAttack:true,
            canAttackLand:true,
            canAttackAir:false,
            weaponType:"cannon-ball",
            pixelWidth:30,
            pixelHeight:30,
            pixelOffsetX:15,
            pixelOffsetY:15,
            radius:13,
            speed:15,
            sight:4,
            cost:1200,
            hitPoints:50,
            turnSpeed:4,
            spriteImages:[
                {name:"stand",count:1,directions:8}         
            ],
        }                       
    }

Reading other post, I have the feeling I should use a for-in loop. The real challenge for me, is to get the right value from my object. I've looked at this post to try and solve it.

I come to a solution looking something like this:

var arr = [];

for (var key in vehicles)
    {
        var obj = vehicle[key];
        for (var prop in obj)
            {
                if(obj.hasOwnProperty(prop))
                {
                    arr.push(prop);
                }
            }
    }

console.log(arr);

But I just get this message from console:

Array[0]length: 0__proto__: Array[0]

I also have a running fiddle here

All help would be highly appreciated.


Solution

  • If you just want the ones in vehicles.list:

    var arr = Object.keys(vehicles.list);
    

    var vehicles = {
      list:{
        "transport":{ //<-- This is the values I want to put to an array
          name:"transport",
          pixelWidth:31,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:15,
          speed:15,
          sight:3,
          cost:400,
          hitPoints:100,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "harvester":{ //<-- This is the values I want to put to an array
          name:"harvester",
          pixelWidth:21,
          pixelHeight:20,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:10,
          speed:10,
          sight:3,
          cost:1600,
          hitPoints:50,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "scout-tank":{ //<-- This is the values I want to put to an array
          name:"scout-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"bullet",
          pixelWidth:21,
          pixelHeight:21,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:11,
          speed:20,
          sight:3,
          cost:500,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "heavy-tank":{ //<-- This is the values I want to put to an array
          name:"heavy-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"cannon-ball",
          pixelWidth:30,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:13,
          speed:15,
          sight:4,
          cost:1200,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        }    
      }
    };
    var arr = Object.keys(vehicles.list);
    snippet.log(arr.join(", "));
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

    If you want all of the keys of the objects referenced by any property of vehicles, then:

    var arr = [];
    Object.keys(vehicles).forEach(function(key) {
      arr.push.apply(arr, Object.keys(vehicles[key]));
    });
    

    The trick there is that we can push an entire array of entries onto arr using arr.push.apply(arr, /*the other array*/).

    var vehicles = {
      list:{
        "transport":{ //<-- This is the values I want to put to an array
          name:"transport",
          pixelWidth:31,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:15,
          speed:15,
          sight:3,
          cost:400,
          hitPoints:100,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "harvester":{ //<-- This is the values I want to put to an array
          name:"harvester",
          pixelWidth:21,
          pixelHeight:20,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:10,
          speed:10,
          sight:3,
          cost:1600,
          hitPoints:50,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "scout-tank":{ //<-- This is the values I want to put to an array
          name:"scout-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"bullet",
          pixelWidth:21,
          pixelHeight:21,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:11,
          speed:20,
          sight:3,
          cost:500,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "heavy-tank":{ //<-- This is the values I want to put to an array
          name:"heavy-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"cannon-ball",
          pixelWidth:30,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:13,
          speed:15,
          sight:4,
          cost:1200,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        }    
      },
      list2: {
        "new-key-for-list2":{
          }
      }
    };
    var arr = [];
    Object.keys(vehicles).forEach(function(key) {
      arr.push.apply(arr, Object.keys(vehicles[key]));
    });
    snippet.log(arr.join(", "));
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

    Or if you really like one-liners, you could use Array#reduce but I think clarity suffers:

    var arr = Object.keys(vehicles).reduce(function(a, key) {
      a.push.apply(a, Object.keys(vehicles[key]));
      return a;
    }, []);
    

    var vehicles = {
      list:{
        "transport":{ //<-- This is the values I want to put to an array
          name:"transport",
          pixelWidth:31,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:15,
          speed:15,
          sight:3,
          cost:400,
          hitPoints:100,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "harvester":{ //<-- This is the values I want to put to an array
          name:"harvester",
          pixelWidth:21,
          pixelHeight:20,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:10,
          speed:10,
          sight:3,
          cost:1600,
          hitPoints:50,
          turnSpeed:2,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "scout-tank":{ //<-- This is the values I want to put to an array
          name:"scout-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"bullet",
          pixelWidth:21,
          pixelHeight:21,
          pixelOffsetX:10,
          pixelOffsetY:10,
          radius:11,
          speed:20,
          sight:3,
          cost:500,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        },
        "heavy-tank":{ //<-- This is the values I want to put to an array
          name:"heavy-tank",
          canAttack:true,
          canAttackLand:true,
          canAttackAir:false,
          weaponType:"cannon-ball",
          pixelWidth:30,
          pixelHeight:30,
          pixelOffsetX:15,
          pixelOffsetY:15,
          radius:13,
          speed:15,
          sight:4,
          cost:1200,
          hitPoints:50,
          turnSpeed:4,
          spriteImages:[
            {name:"stand",count:1,directions:8}         
          ],
        }    
      },
      list2: {
        "new-key-for-list2":{
          }
      }
    };
    var arr = Object.keys(vehicles).reduce(function(a, key) {
      a.push.apply(a, Object.keys(vehicles[key]));
      return a;
    }, []);
    snippet.log(arr.join(", "));
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>


    Note that Object.keys and Array#forEach (and Array#reduce) were all added in ES5 (2009-ish), so they're in all modern browsers, but missing from IE8 and other similar old browsers. All three can be polyfilled, though.