I have a JavaScript object array. When write console.log(myarry) it will show in the console in the below form.
Array[2]
0: Object
one: "one"
1: Object
two: "two"
length: 2
In this array my key and value are same and am trying to get the key or value to a variable and print it. When am trying the below code it showing:
object object
for (var key in myarry) {
alert("Key is " + key + ", value is" + myarry[key]);
}
check this snippet
var obj = [{
"1": "one"
}, {
"2": "two"
}]
obj.forEach(function(item) {
Object.keys(item).forEach(function(key) {
console.log("key:" + key + "value:" + item[key]);
});
});
Hope it helps
Use for-loop instead of for-in to iterate array.
Use Object.keys to get keys of object
var arr = [{
one: 'one'
}, {
two: 'two'
}];
for (var i = 0, l = arr.length; i < l; i++) {
var keys = Object.keys(arr[i]);
for (var j = 0, k = keys.length; j < k; j++) {
console.log("Key:" + keys[j] + " Value:" + arr[i][keys[j]]);
}
}
I think you have two main options to get keys of an object using Object.keys these are: forEach; or a simple for.
1. Use forEach
If you're using an environment that supports the Array features of ES5 (directly or using a shim), you can use the new forEach:
var myarray = [{one: 'one'}, {two: 'two'}];
myarray.forEach(function(item) {
var items = Object.keys(item);
items.forEach(function(key) {
console.log('this is a key-> ' + key + ' & this is its value-> ' + item[key]);
});
});
forEach accepts an iterator function and, optionally, a value to use as this when calling that iterator function (not used above). The iterator function is called for each entry in the array, in order, skipping non-existent entries in sparse arrays. Although
forEach has the benefit that you don't have to declare indexing and value variables in the containing scope, as they're supplied as arguments to the iteration function, and so nicely scoped to just that iteration.
If you're worried about the runtime cost of making a function call for each array entry, don't be; technical details.
2. Use a simple for
Sometimes the old ways are the best:
var myarray = [{one: 'one'}, {two: 'two'}];
for (var i = 0, l = myarray.length; i < l; i++) {
var items = myarray[i];
var keys = Object.keys(items);
for (var j = 0, k = keys.length; j < k; j++) {
console.log('this is a key-> ' + keys[j] + ' & this is its value-> ' + items[keys[j]]);
}
}
Depending on your construction, you can do
const arr = [{ key1: 'val1' }, { key2: 'val2' }]
arr.forEach((a, i) =>
console.log(i, [{ key: Object.keys(a) }, { val: Object.values(a) }])
)
and to answer your question
arr.forEach((a, i) =>
alert("Key is "+ Object.keys(a) + ", value is " + Object.values(a))
)
am trying to get the key or value to a variable and print it.
then you could
var myarry = [{ one: 'one' }, { two: 'two' }];
for (var key in myarry) {
var value = myarry[key];
console.log(key, value)
}
you can do it in this way
const a = [{ one: 'one' }, { two: 'two' }];
a.forEach(function(value,key) {
console.log(value,key);
});
You can take key and value in a variable and use them.
Here's an interesting way to do it.
const arr = [{ one: 'one' }, { two: 'two' }];
Object.entries(arr).forEach(([_, obj]) => {
const key = Object.keys(obj)[0];
console.log(`Key is ${key}, value is ${obj[key]}.`);
});
Related
I have an object in JavaScript:
{
abc: '...',
bca: '...',
zzz: '...',
xxx: '...',
ccc: '...',
// ...
}
I want to use a for loop to get its properties. And I want to iterate it in parts (not all object properties at once).
With a simple array I can do it with a standard for loop:
for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last
But how to do it with objects?
For iterating on keys of Arrays, Strings, or Objects, use for .. in :
for (let key in yourobject) {
console.log(key, yourobject[key]);
}
With ES6, if you need both keys and values simultaneously, do
for (let [key, value] of Object.entries(yourobject)) {
console.log(key, value);
}
To avoid logging inherited properties, check with hasOwnProperty :
for (let key in yourobject) {
if (yourobject.hasOwnProperty(key)) {
console.log(key, yourobject[key]);
}
}
You don't need to check hasOwnProperty when iterating on keys if you're using a simple object (for example one you made yourself with {}).
This MDN documentation explains more generally how to deal with objects and their properties.
If you want to do it "in chunks", the best is to extract the keys in an array. As the order isn't guaranteed, this is the proper way. In modern browsers, you can use
let keys = Object.keys(yourobject);
To be more compatible, you'd better do this :
let keys = [];
for (let key in yourobject) {
if (yourobject.hasOwnProperty(key)) keys.push(key);
}
Then you can iterate on your properties by index: yourobject[keys[i]] :
for (let i=300; i < keys.length && i < 600; i++) {
console.log(keys[i], yourobject[keys[i]]);
}
Here is another iteration solution for modern browsers:
Object.keys(obj)
.filter((k, i) => i >= 100 && i < 300)
.forEach(k => console.log(obj[k]));
Or without the filter function:
Object.keys(obj).forEach((k, i) => {
if (i >= 100 && i < 300) {
console.log(obj[k]);
}
});
However you must consider that properties in JavaScript object are not sorted, i.e. have no order.
Using Object.entries you do something like this.
// array like object with random key ordering
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]
The Object.entries() method returns an array of a given object's own enumerable property [key, value]
So you can iterate over the Object and have key and value for each of the object and get something like this.
const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
const key = obj[0];
const value = obj[1];
// do whatever you want with those values.
});
or like this
// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
For a reference have a look at the MDN docs for Object Entries
With the new ES6/ES2015 features, you don't have to use an object anymore to iterate over a hash. You can use a Map. Javascript Maps keep keys in insertion order, meaning you can iterate over them without having to check the hasOwnProperty, which was always really a hack.
Iterate over a map:
var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
for (var key of myMap.keys()) {
console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"
for (var value of myMap.values()) {
console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"
for (var [key, value] of myMap.entries()) {
console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
or use forEach:
myMap.forEach(function(value, key) {
console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"
If you want the key and value when iterating, you can use a for...of loop with Object.entries.
const myObj = {a: 1, b: 2}
for (let [key, value] of Object.entries(myObj)) {
console.log(`key=${key} value=${value}`)
}
// output:
// key=a value=1
// key=b value=2
The only reliable way to do this would be to save your object data to 2 arrays, one of keys, and one for the data:
var keys = [];
var data = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
}
}
You can then iterate over the arrays like you normally would:
for(var i = 0; i < 100; i++){
console.log(keys[i], data[i]);
//or
console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
console.log(keys[i], data[i]);
}
I am not using Object.keys(obj), because that's IE 9+.
->if we iterate over a JavaScript object using and find key of array of
objects
Object.keys(Array).forEach(key => {
console.log('key',key)
})
If you have a simple object you can iterate through it using the following code:
let myObj = {
abc: '...',
bca: '...',
zzz: '...',
xxx: '...',
ccc: '...',
// ...
};
let objKeys = Object.keys(myObj);
//Now we can use objKeys to iterate over myObj
for (item of objKeys) {
//this will print out the keys
console.log('key:', item);
//this will print out the values
console.log('value:', myObj[item]);
}
If you have a nested object you can iterate through it using the following code:
let b = {
one: {
a: 1,
b: 2,
c: 3
},
two: {
a: 4,
b: 5,
c: 6
},
three: {
a: 7,
b: 8,
c: 9
}
};
let myKeys = Object.keys(b);
for (item of myKeys) {
//print the key
console.log('Key', item)
//print the value (which will be another object)
console.log('Value', b[item])
//print the nested value
console.log('Nested value', b[item]['a'])
}
If you have array of objects you can iterate through it using the following code:
let c = [
{
a: 1,
b: 2
},
{
a: 3,
b: 4
}
];
for(item of c){
//print the whole object individually
console.log('object', item);
//print the value inside the object
console.log('value', item['a']);
}
const o = {
name: "Max",
location: "London"
};
for (const [key, value] of Object.entries(o)) {
console.log(`${key}: ${value}`);
}
Try online
Define object in arguments and avoid selectors & subscripts
There are a number of syntax choices but this one defines the object upfront in the closure's arguments which eliminates the need for selectors or subscripts in the iterator. k is key, v is value, i is index.
const obj = {
kiwi: true,
mango: false,
pineapple: 500
};
Object.entries(obj).forEach(([k, v], i) => {
console.log(k, v, i);
});
// kiwi true 0
// mango false 1
// pineapple 500 2
If you wanted to iterate the whole object at once you could use for in loop:
for (var i in obj) {
...
}
But if you want to divide the object into parts in fact you cannot. There's no guarantee that properties in the object are in any specified order. Therefore, I can think of two solutions.
First of them is to "remove" already read properties:
var i = 0;
for (var key in obj) {
console.log(obj[key]);
delete obj[key];
if ( ++i > 300) break;
}
Another solution I can think of is to use Array of Arrays instead of the object:
var obj = [['key1', 'value1'], ['key2', 'value2']];
Then, standard for loop will work.
I finally came up with a handy utility function with a unified interface to iterate Objects, Strings, Arrays, TypedArrays, Maps, Sets, (any Iterables).
const iterate = require('#a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };
iterate(obj, (value, key) => console.log(key, value));
// a 1
// b 2
// c 3
https://github.com/alrik/iterate-javascript
Really a PITA this is not part of standard Javascript.
/**
* Iterates the keys and values of an object. Object.keys is used to extract the keys.
* #param object The object to iterate
* #param fn (value,key)=>{}
*/
function objectForEach(object, fn) {
Object.keys(object).forEach(key => {
fn(object[key],key, object)
})
}
Note: I switched the callback parameters to (value,key) and added a third object to make the API consistent other APIs.
Use it like this
const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
// do something
});
For object iteration we usually use a for..in loop. This structure will loop through all enumerable properties, including ones who are inherited via prototypal inheritance. For example:
let obj = {
prop1: '1',
prop2: '2'
}
for(let el in obj) {
console.log(el);
console.log(obj[el]);
}
However, for..in will loop over all enumerable elements and this will not able us to split the iteration in chunks. To achieve this we can use the built in Object.keys() function to retrieve all the keys of an object in an array. We then can split up the iteration into multiple for loops and access the properties using the keys array. For example:
let obj = {
prop1: '1',
prop2: '2',
prop3: '3',
prop4: '4',
};
const keys = Object.keys(obj);
console.log(keys);
for (let i = 0; i < 2; i++) {
console.log(obj[keys[i]]);
}
for (let i = 2; i < 4; i++) {
console.log(obj[keys[i]]);
}
Yes. You can loop through an object using for loop. Here is an example
var myObj = {
abc: 'ABC',
bca: 'BCA',
zzz: 'ZZZ',
xxx: 'XXX',
ccc: 'CCC',
}
var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
console.log (k[i] + ": " + myObj[k[i]]);
}
NOTE: the example mentioned above will only work in IE9+. See Objec.keys browser support here.
Here is a Hand Made Solution:
function iterationForObject() {
let base = 0,
Keys= Object.keys(this);
return {
next: () => {
return {
value: {
"key": Keys[base],
"value": this[Keys[base]]
},
done: !(base++ < Keys.length)
};
}
};
}
Object.prototype[Symbol.iterator] = iterationForObject;
And Then You Can Loop Any Object:
for ( let keyAndValuePair of (Object Here) ) {
console.log(`${keyAndValuePair.key} => ${keyAndValuePair.value}`);
}
<script type="text/javascript">
// method 1
var images = {};
images['name'] = {};
images['family'] = {};
images[1] = {};
images['name'][5] = "Mehdi";
images['family'][8] = "Mohammadpour";
images['family']['ok'] = 123456;
images[1][22] = 2602;
images[1][22] = 2602;
images[1][22] = 2602;
images[1][22] = 2602;
images[1][23] = 2602;
for (const [key1, value1] of Object.entries(images)){
for (const [key2, value2] of Object.entries(value1)){
console.log(`${key1} => ${key2}: ${value2}`);
}
}
console.log("=============================");
// method 2
var arr = [];
for(var x = 0; x < 5; x++){
arr[x] = [];
for(var y = 0; y < 5; y++){
arr[x][y] = x*y;
}
}
for(var i = 0; i < arr.length; i++) {
var cube = arr[i];
for(var j = 0; j < cube.length; j++) {
console.log("cube[" + i + "][" + j + "] = " + cube[j]);
}
}
</script>
var Dictionary = {
If: {
you: {
can: '',
make: ''
},
sense: ''
},
of: {
the: {
sentence: {
it: '',
worked: ''
}
}
}
};
function Iterate(obj) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && isNaN(prop)) {
console.log(prop + ': ' + obj[prop]);
Iterate(obj[prop]);
}
}
}
Iterate(Dictionary);
You can try using lodash- A modern JavaScript utility library delivering modularity, performance & extras js to fast object iterate:-
var users = {
'fred': {
'user': 'fred',
'age': 40
},
'pebbles': {
'user': 'pebbles',
'age': 1
}
};
_.mapValues(users, function(o) {
return o.age;
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users, 'age')); // returns age property & value
console.log(_.mapValues(users, 'user')); // returns user property & value
console.log(_.mapValues(users)); // returns all objects
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>
By looking at the "Array" image, how can I access all levels of this array?
I tried doing a foreach but this only allows me to access to the first object, I can't acces the second object filled with strings.
for (var key in result)
{
if (result.hasOwnProperty(key))
{
console.log(key, result[key]);
for(var item in result[key])
{
console.log(item);
}
}
}
I also tried:
result[key[item]]
But it appears to be undifined.
I know it's easy to access all elements by the name, but the names change constantly, so the solution should be dynamic.
I added the Demo on the comments to see behavior.
Object.keys(obj) returns an array of the keys in obj.
var obj = {
a: 1,
b: 2,
m: 3,
x: 4,
y: 5,
z: 6
}
//get all the keys in an array:
var keys = Object.keys(obj)
console.log("keys: " + keys);
//iterate through the object by its keys:
for (var i = 0; i < keys.length; i++){
console.log("key " + keys[i] + " has value " + obj[keys[i]]);
}
Update based on your comment
I think you're asking to apply this solution to an arbitrary-depth object. My solution would be to wrap the previous trick in a function and call it recursively if there are nested objects:
var obj = {
a: {foo:"bar",foof:"barf"},
b: 2,
m: 3,
x: {baz:{really:{more:{objects: "yeah, there could be a lot"}}}},
y: 5,
z: 6
}
function getKeysDeep(obj,prefix){
//get all the keys in an array:
var keys = Object.keys(obj)
//console.log(prefix + "keys: " + keys);
//iterate through the object by its keys:
for (var i = 0; i < keys.length; i++){
if (obj[keys[i]] !== null && typeof obj[keys[i]] === 'object') {
console.log("key " + keys[i] + "'s value is an object");
getKeysDeep(obj[keys[i]],prefix + keys[i] + ": ");
} else {
console.log(prefix + "key " + keys[i] + " has value " + obj[keys[i]]);
}
}
}
getKeysDeep(obj,"")
This loop worked too!
Object.keys(result).forEach(function (key) {
console.log(result[key]);
var test = result[key];
Object.keys(test).forEach(function (key) {
console.log(test[key]);
var testTwo = test[key];
Object.keys(testTwo).forEach(function (key) {
console.log(testTwo[key]);
var testThree = testTwo[key];
});
});
});
But #nvioli answer is more accurate.
I have the following object:
{ apple: 'banana',
banana: [ 'pear', 'apple' ],
melon: 'apple',
grapes: 'peach',
carrot: 'apple',
peach: 'grapes' }
I am basically tying to find any 'circular references', for example:
apple: 'banana',
banana: ['apple']
and
grapes: 'peach',
peach: 'grapes'
I've spent ages and have tried a number of different approaches, including copying the key and values into a new array, sorting and trying to match - now I'm not even sure what the best way to tackle this is.
Edit: Thanks to everyone for their help. I think it wasn't quite clear with my original question. I was only wanting to identify the case where there exists a reference in both directions. So apple->banana, banana<-apple and grapes->peach, peach<-grapes should match. But melon->apple, banana->apple and carrot->apple should not match at all.
I've got it working with the following (fairly disgraceful) code:
var data = { apple: 'banana',
banana: ['test', 'apple'],
melon: 'apple',
grapes: 'peach',
carrot: 'apple',
peach: 'grapes' };
var arr = [], arr2 = [], u = {}
//Iterate over object 'data' and create an array of arrays - sorted alphabetically
for (var item in data) {
var val = data[item];
if (Array.isArray(val)) {
for (var i = 0; i < val.length; ++i) {
arr.push(new Array(item, val[i]).sort())
}
} else {
arr.push(new Array(item, val).sort())
}
}
//Iterate of arr and look for any matches..
for(var i = 0, l = arr.length; i < l; ++i){
if(u.hasOwnProperty(arr[i])) {
arr2.push(arr[i]);
}
u[arr[i]] = 1;
}
console.log('Matches found: ' + arr2)
//prints: 'Matches found: [ [ 'apple', 'banana' ], [ 'grapes', 'peach' ] ]
Here's one approach in a working snippet:
var data = { apple: 'banana',
banana: [ 'pear', 'apple' ],
melon: 'apple',
grapes: 'peach',
carrot: 'apple',
peach: 'grapes' };
for (var item in data) {
var val = data[item];
if (Array.isArray(val)) {
for (var i = 0; i < val.length; i++) {
if (val[i] in data) {
document.write("circular reference for '" + val[i] + "' in " + item + ":[" + val[i] + "]<br>" );
}
}
} else {
if (val in data) {
document.write("circular reference for '" + val + "' in " + item + ":" + val + "<br>");
}
}
}
It generates this output:
circular reference for 'banana' in apple:banana
circular reference for 'apple' in banana:[apple]
circular reference for 'apple' in melon:apple
circular reference for 'peach' in grapes:peach
circular reference for 'apple' in carrot:apple
circular reference for 'grapes' in peach:grapes
Do you just want direct links? Just check to see if any of the values are keys and if so, if they point to the original key.
_.mapObject(fruit, function(key, val) {
if(fruit[val] && (fruit[val] === key || fruit[val].includes(key))){
console.log(key + ':' + val + ' match!');
}
});
Do you want any circular references? You need a 'visited' array. You're essentially trying to do graph traversal so you can take a look at canonical examples like Dijkstra's.
None language specific approach
Keep a multi-dimensional array/map of keys/values. (Outer array elements = each key name, Inner array elements = values for key)
// Psuedo-Code
// Test: If any element in the outer array exists with the the inner array, check // for self within each inner key's inner array
isCircular(JSON Object) {
// Assume No Circular Reference
var isCircular = false;
// Check all the Keys for Circular references
nextKey = firstKey;
while (nextKey != null)
// Setup loop
var parent = nextKey;
var child = null;
foreach child in parent.values {
// Check the child.value for parent
foreach value in child.value {
// If parent exists, there is a circular reference
if (value == parent) isCircular = true; // CIRCULAR REFERENCE
}
}
nextKey++; // Next Element
}
return isCircular;
}
I have an array that is sorted in the following way
var items = [2.99, 5.99, 23.99, 1.99];
items.sort(function(a,b) { return a - b;});
This outputs the following:
[1.99, 2.99, 5.99, 23.99]
But I need a way to sort it but keep an index of the original index, e.g.
[3: 1.99, 0: 2.99, 1: 5.99, 2:23.99]
Any help would be appreciated.
Map it to an array of objects.
So in the resulting array, each member is an object with an n property that holds the number, and an i property that holds the original index.
You can then iterate that array and get the data like normal.
var items = [2.99, 5.99, 23.99, 1.99];
var arr_of_objs = items.map(function(n, i) {
return { n:n, i:i };
}).sort(function(a, b) {
return a.n - b.n;
});
arr_of_objs.forEach(function(obj, i) {
this.textContent += "number: " + obj.n + ", orig idx: " + obj.i + ", new idx: " + i + "\n";
}, document.querySelector("pre"));
<pre></pre>
var items = [2.99, 5.99, 23.99, 1.99];
var sortable = [];
for (var i = 0; i < items.length; i++) {
sortable.push([i, items[i]]);
}
sortable.sort(function(a, b) {
return a[1] - b[1]
});
console.log(sortable);
Unfortunately it is not possible in JS get sorting in this case. JS understands array only as [0: 1.99, 1:2.99, 3:23.99] -- you cannot change order of indexes. But you can use array of arrays or array of object to solve the problem.
var items = [2.99, 5.99, 23.99, 1.99];
function PreserveKeysSorting(arr) {
var arr = arr
obj = [];
for(i in arr) {
obj.push({index: i, value: arr[i]});
}
obj.sort(function(a,b) { return a.value - b.value;});
return obj;
}
console.log(items);
console.log(PreserveKeysSorting(items));
Live Demo -- http://jsfiddle.net/u1g0xsap/1/
The array that you want as a result is not valid, but you can do something like this:
First make an array that contains objects that persists the index:
var itemsObj = [];
items.forEach(function(value, index) {
itemsObj.push({
value: value,
index: index
});
});
Then you can sort them like this:
items.sort(function(a,b) { return a.value - b.value;});
and you will get an arary of objects like this
[{index:3, value: 1.99}, {index: 0, value: 2.99}, {index: 1, value: 5.99}, {index:2, value:23.99}]
Hardcode the index into the array:
var items = [2.99, 5.99, 23.99, 1.99]
var itemsWithIndex = [];
for (i=0; i<items.length; i++) { itemsWithIndex[i] = [i+1, items[i]]; }
itemsWithIndex.sort(function(a,b) { return a[1]-b[1]; });
Note that an auxiliary variable (itemsWithIndex) was added for clarity, but you can also just update the original array:
var items = [2.99, 5.99, 23.99, 1.99]
for (i=0; i<items.length; i++) { items[i] = [i+1, items[i]]; }
items.sort(function(a,b) { return a[1]-b[1]; });
You could use two arrays and indexOf() method:
// Variables
var items = items_sort = [2.99, 5.99, 23.99, 1.99];
var order = new Array();
// Sort array
items_sort.sort(function(a,b) { return a - b;});
// Get order
for (i = 0; i < items.length; i++) {
order[i] = items.indexOf(items_sort[i]);
}
I have an associative array like:
var arr = {};
arr['alz'] = '15a';
arr['aly'] = '16b';
arr['alx'] = '17a';
arr['alw'] = '09c';
I need to find the previous and next key of any selected element. Say, for key 'aly' it will be 'alz' and 'alx'. If possible, I want to access the array by index rather than the key.
Currently, I am doing this using a separate array containing keys, e.g.
var arrkeys = ['alz','aly','alx','alw'];
Ordering of the object's properties is undefined. You can use this structure...
[{ key: 'alz', value: '15a'},
{ key: 'aly', value: '16b'},
{ key: 'alx', value: '17a'}]
... though searching for the element with the given key (like 'give me the element which key is 'alz') is not as straight-forward as with simple object. That's why using it like you did - providing a separate array for ordering of the indexes - is another common approach. You can attach this array to that object, btw:
var arr={};
arr['alz']='15a';
arr['aly']='16b';
arr['alx']='17a';
arr['alw']='09c';
arr._keysOrder = ['alz', 'aly', 'alx', 'alw'];
This is an object, not an array, and it sounds like you don't really want those strings to be keys.
How about a nice array?
var ar = [
{ key: 'alz', value: '15a' },
{ key: 'aly', value: '16b' },
{ key: 'alx', value: '17a' },
{ key: 'alw', value: '09c' }
];
How about adding some syntactic sugar in the form of an OrderedObject object? Then you could do something like this:
myObj = new OrderedObject();
myObj.add('alz', '15a');
myObj.add('aly', '16b');
myObj.add('alx', '17a');
myObj.add('alw', '09c');
console.log(myObj.keyAt(2)); // 'alx'
console.log(myObj.valueAt(3)); // '09c'
console.log(myObj.indexOf('aly')); // 1
console.log(myObj.length()) // 4
console.log(myObj.nextKey('aly')); // 'alx'
The following code makes this work. See it in action in a jsFiddle.
function OrderedObject() {
var index = [];
this.add = function(key, value) {
if (!this.hasOwnProperty(key)) {
index.push(key);
}
this[key] = value;
};
this.remove = function(key) {
if (!this.hasOwnProperty(key)) { return; }
index.splice(index.indexOf(key), 1);
delete this[key];
}
this.indexOf = function(key) {
return index.indexOf(key);
}
this.keyAt = function(i) {
return index[i];
};
this.length = function() {
return index.length;
}
this.valueAt = function(i) {
return this[this.keyAt(i)];
}
this.previousKey = function(key) {
return this.keyAt(this.indexOf(key) - 1);
}
this.nextKey = function(key) {
return this.keyAt(this.indexOf(key) + 1);
}
}
I made some decisions that may not work for you. For example, I chose to use an Object as the prototype rather than an Array, so that you could preserve enumerating your object with for (key in myObj). But it didn't have to be that way. It could have been an Array, letting you use the property .length instead of the function .length() and then offering an each function that enumerates the keys, or perhaps an .object() function to return the inner object.
This could be a little awkward as you'd have to remember not to add items to the object yourself. That is, if you do myObj[key] = 'value'; then the index will not be updated. I also did not provide any methods for rearranging the order of things or inserting them at a particular position, or deleting by position. If you find my object idea useful, though, I'm sure you can figure out how to add such things.
With the newer versions of EcmaScript you can add true properties and make them non-enumerable. This would allow the new object to more seamlessly and smoothly act like the ideal OrderedObject I am imagining.
If you have to know the order of everything, and still use the keys and values, try this:
var arr = [
{ key: 'alz', value: '15a' },
{ key: 'aly', value: '16b' },
{ key: 'alx', value: '17a' },
{ key: 'alw', value: '09c' }
];
You can then access them sequentially as follows: arr[0].key and arr[0].value. Similarly, you can find siblings inside of the loop with the following:
for(var i = 0; i < arr.length; i++)
{
var previous_key = (i > 0) ? arr[(i - 1)].key : false;
var next_key = (i < (arr.length - 1)) ? arr[(i + 1)].key : false;
}
You may try this
function sortObject(obj, order)
{
var list=[], mapArr = [], sortedObj={};
for(var x in obj) if(obj.hasOwnProperty(x)) list.push(x);
for (var i=0, length = list.length; i < length; i++) {
mapArr.push({ index: i, value: list[i].toLowerCase() });
}
mapArr.sort(function(a, b) {
if(order && order.toLowerCase()==='desc')
return a.value < b.value ? 1 : -1;
else return a.value > b.value ? 1 : -1;
});
for(var i=0; i<mapArr.length;i++)
sortedObj[mapArr[i].value]=obj[mapArr[i].value];
return sortedObj;
}
// Call the function to sort the arr object
var sortedArr = sortObject(arr); // Ascending order A-Z
var sortedArr = sortObject(arr, 'desc'); // Descending order Z-A
DEMO.
Remember, this will return a new object and original object will remain unchanged.