[javascript] How to get array keys in Javascript?

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.

This question is related to javascript arrays key

The answer is


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 />");
}

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

or

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

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)

... ????

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(''));

    }

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"]


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)


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]);
}

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.


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

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"]

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


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 ...


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to key

How do I check if a Key is pressed on C++ Map<String, String>, how to print both the "key string" and "value string" together Python: create dictionary using dict() with integer keys? SSH Key: “Permissions 0644 for 'id_rsa.pub' are too open.” on mac SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch How to get the stream key for twitch.tv How to get key names from JSON using jq How to add multiple values to a dictionary key in python? Initializing a dictionary in python with a key value and no corresponding values How can I sort a std::map first by value, then by key?