How to iterate array keys in Javascript?

JavascriptArraysKey

Javascript Problem Overview


I have an array created with this code:

var widthRange = new Array();
widthRange[46] = { min:0,  max:52 };
widthRange[66] = { min:52, max:70 };
widthRange[90] = { min:70, max:94 };

I want to get each of the values 46, 66, 90 in a loop. I tried for (var key in widthRange) but this gives me a whole bunch of extra properties (I assume they are functions on the object). I can't use a regular for loop since the values are not sequential.

Javascript Solutions


Solution 1 - Javascript

You need to call the hasOwnProperty function to check whether the property is actually defined on the object itself (as opposed to its prototype), like this:

for (var key in widthRange) {
    if (key === 'length' || !widthRange.hasOwnProperty(key)) continue;
    var value = widthRange[key];
}

Note that you need a separate check for length.
However, you shouldn't be using an array here at all; you should use a regular object. All Javascript objects function as associative arrays.

For example:

var widthRange = { };  //Or new Object()
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

Solution 2 - Javascript

The stringified keys can be queried with Object.keys(array).

Solution 3 - Javascript

If you are doing any kind of array/collection manipulation or inspection I highly recommend using Underscore.js. It's small, well-tested and will save you days/weeks/years of javascript headache. Here is its keys function:

Keys

Retrieve all the names of the object's properties.

_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]

Solution 4 - Javascript

Say your array looked like arr = [ { a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }, { a: 7, b: 8, c: 9 } ] (or possibly other keys) you could do

arr.map((o) => {
	return Object.keys(o)
}).reduce((prev, curr) => {
	return prev.concat(curr)
}).filter((col, i, array) => {
	return array.indexOf(col) === i
});

["a", "b", "c"]

Solution 5 - Javascript

for (var i = 0; i < widthRange.length; ++i) {
  if (widthRange[i] != null) {
    // do something
  }
}

You can't really get just the keys you've set because that's not how an Array works. Once you set element 46, you also have 0 through 45 set too (though they're null).

You could always have two arrays:

var widthRange = [], widths = [], newVal = function(n) {
  widths.push(n);
  return n;
};
widthRange[newVal(26)] = { whatever: "hello there" };

for (var i = 0; i < widths.length; ++i) {
  doSomething(widthRange[widths[i]]);
}

edit well it may be that I'm all wet here ...

Solution 6 - Javascript

widthRange.map(function(_, i) { return i });

or

widthRange.map((_, i) => i);

Solution 7 - Javascript

Your original example works just fine for me:

<html>
<head>
</head>
<body>
<script>
var widthRange = new Array();
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

var i = 1;
for (var key in widthRange)
{
	document.write("Key #" + i + " = " + key + "; &nbsp;&nbsp;&nbsp; min/max = " + widthRange[key].min + "/" + widthRange[key].max + "<br />");
	i++;
}
</script>
</html>

Results in the browser (Firefox 3.6.2 on Windows XP):

Key #1 = 46;     min/max = 0/52
Key #2 = 66;     min/max = 52/70
Key #3 = 90;     min/max = 70/94

Solution 8 - Javascript

I think you should use an Object ({}) and not an array ([]) for this.

A set of data is associated with each key. It screams for using an object. Do:

var obj = {};
obj[46] = { sel:46, min:0,  max:52 };
obj[666] = { whatever:true };

// This is what for..in is for
for (var prop in obj) {
  console.log(obj[prop]);
}

Maybe some utility stuff like this can help:

window.WidthRange = (function () {
  var obj = {};
  return {
    getObj: function () {return obj;}
    , add: function (key, data) {
        obj[key] = data;
        return this; // enabling chaining
      }
  }
})();

// Usage (using chaining calls):
WidthRange.add(66, {foo: true})
.add(67, {bar: false})
.add(69, {baz: 'maybe', bork:'absolutely'});

var obj = WidthRange.getObj();
for (var prop in obj) {
  console.log(obj[prop]);
}

Solution 9 - Javascript

To generate an Array from an Array's keys, use

Array.from(Array(10).keys());

The example above will give an array of 0 to 9. It is not exactly what you asked for but I hope this gives an insight into this method.

Solution 10 - Javascript

Seems to work.

var widthRange = new Array();
widthRange[46] = { sel:46, min:0,  max:52 };
widthRange[66] = { sel:66, min:52, max:70 };
widthRange[90] = { sel:90, min:70, max:94 };

for (var key in widthRange)
{
    document.write(widthRange[key].sel + "<br />");
	document.write(widthRange[key].min + "<br />");
	document.write(widthRange[key].max + "<br />");
}

Solution 11 - Javascript

I wrote a function what works fine with every instance of Objects (Arrays are those).

Object.prototype.toArray = function()
{
    if(!this)
    {
      return null;
    }

    var c = [];

    for (var key in this) 
    {
        if ( ( this instanceof Array && this.constructor === Array && key === 'length' ) || !this.hasOwnProperty(key) ) 
        {
            continue;
        }

        c.push(this[key]);
    }

    return c;
};

Usage:

var a   = [ 1, 2, 3 ];
a[11]   = 4;
a["js"] = 5;

console.log(a.toArray());

var b = { one: 1, two: 2, three: 3, f: function() { return 4; }, five: 5 };
b[7] = 7;

console.log(b.toArray());

Output:

> [ 1, 2, 3, 4, 5 ]
> [ 7, 1, 2, 3, function () { return 4; }, 5 ]

It may be useful for anyone.

Solution 12 - Javascript

... ????

Alternatively, if you have a list of items you want to use...

var range = [46, 66, 90]
	, widthRange=[]
	, write=[];
	
	widthRange[46] = { min:0, max:52 }; 
	widthRange[66] = { min:52, max:70 }; 
	widthRange[90] = { min:70, max:94 }; 
	
for(var x=0; x<range.length; x++){var key, wr;

	key = range[x];
	
	wr = widthRange[key] || false;
	
	if(wr===false){continue;}
	
	write.push(['key: #',key, ', min: ', wr.min, 'max:', wr.max].join(''));
	
	}

Solution 13 - Javascript

For your input data:

let widthRange = new Array()
widthRange[46] = { min:0,  max:52 }
widthRange[61] = { min:52, max:70 }
widthRange[62] = { min:52, max:70 }
widthRange[63] = { min:52, max:70 }
widthRange[66] = { min:52, max:70 }
widthRange[90] = { min:70, max:94 }

Declarative approach:

const relevantKeys = [46,66,90]
const relevantValues = Object.keys(widthRange)
    .filter(index => relevantKeys.includes(parseInt(index)))
    .map(relevantIndex => widthRange[relevantIndex])

Object.keys to get the keys, using parseInt to cast them as numbers. filter to get only ones you want. map to build an array from the original object of just the indices you're after, since Object.keys loses the object values.

Debug:

console.log(widthRange)
console.log(relevantKeys)
console.log(relevantValues)

Solution 14 - Javascript

The question is pretty old, but nowadays you can use forEach, which is efficient and will retain the keys as numbers:

let keys = widthRange.map((v,k) => k).filter(i=>i!==undefined))

This loops through widthRange and makes a new array with the value of the keys, and then filters out all sparce slots by only taking the values that are defined.

(Bad idea, but for thorughness: If slot 0 was always empty, that could be shortened to filter(i=>i) or filter(Boolean)

And, it may be less efficient, but the numbers can be cast with let keys = Object.keys(array).map(i=>i*1)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDisgruntledGoatView Question on Stackoverflow
Solution 1 - JavascriptSLaksView Answer on Stackoverflow
Solution 2 - JavascriptthSoftView Answer on Stackoverflow
Solution 3 - JavascriptMike McKayView Answer on Stackoverflow
Solution 4 - JavascriptMortenView Answer on Stackoverflow
Solution 5 - JavascriptPointyView Answer on Stackoverflow
Solution 6 - JavascriptalexndreazevedoView Answer on Stackoverflow
Solution 7 - JavascriptAndy ShellamView Answer on Stackoverflow
Solution 8 - JavascriptnpupView Answer on Stackoverflow
Solution 9 - JavascriptNeelansh MathurView Answer on Stackoverflow
Solution 10 - JavascriptMichael D. IrizarryView Answer on Stackoverflow
Solution 11 - JavascriptschwarzkopfbView Answer on Stackoverflow
Solution 12 - JavascriptYann CarterView Answer on Stackoverflow
Solution 13 - JavascriptS..View Answer on Stackoverflow
Solution 14 - JavascriptSamGoodyView Answer on Stackoverflow