How to find common properties between JavaScript objects - javascript

What is the best/most efficient way to find the common/different properties of an array of objects.
I need to identify the set of properties that exists in all objects and all have the same value(the common).
Preferably I would also like to get an array with all other properties (the diff).
I have searched for an efficient library/function that can do it. But didn't find anything. So I tried on my own.
Consider this array of JS objects:
var objects = [{
id: '2j2w4f',
color: 'red',
height: 20,
width: 40,
owner: 'bob'
}, {
id: '2j2w3f',
color: 'red',
height: 20,
width: 41,
owner: 'bob'
}, {
id: '2j2w2f',
color: 'red',
height: 21,
}, {
id: '2j2w1f',
color: 'red',
height: 21,
width: 44
}];
I would like to identify color (with value red) as the only common property.
Note that they do not have the same set of properties. E.g. owner is not a common property.
This is my own attempt to solve it (using lodash):
function commonDifferentProperties(objects) {
// initialize common as first object, and then remove non-common properties.
var common = objects[0];
var different = [];
var i, obj;
// iterate through the rest (note: i === 0 is not supposed to be covered by this)
for (i = objects.length - 1; i > 0; i--) {
obj = objects[i];
// compare each property of obj with current common
_.forOwn(obj, function (value, key) {
// if property not in current common it must be different
if (_.isUndefined(common[key])) {
if (!_.contains(different, key)) {
different.push(key);
}
} else if (common[key] !== value) { // remove property from common if value is not the same
delete common[key];
different.push(key);
}
});
// check that all properties of common is present in obj, if not, remove from common.
_.forOwn(common, function (value, key) {
if (_.isUndefined(obj[key])) {
delete common[key];
different.push(key);
}
});
}
return {
common: common,
different: different
};
}
jsFiddle with the example
I have also tried a mapReduce approach, but that seemed even worse.
I still think this seems a bit complex/time consuming, and I will do this on 1000-10000 objects or more with 20-50 properties each.
Any suggestions?

There are two things that are look wrong in your solution:
By var common = objects[0]; you don't copy the object, so you're going to corrupt the objects
You both check that all properties of common is present in obj, but also compare each property of obj with current common. That seems to be once too much. Didn't realize at first that you needed the different properties as well.
I'd loop over the data in two passes. In the first, you collect all apparent properties in one object, in the second you test whether they're common or not:
function commonDifferentProperties(objects) {
var common = _.reduce(objects, function(acc, obj) {
for (var p in obj)
acc[p] = obj[p];
return acc;
}, {});
var different = _.reduce(objects, function(acc, obj) {
for (var p in common)
if (common[p] !== obj[p]) {
delete common[p];
acc.push(p);
}
return acc;
}, []);
return {
common: common,
different: different
};
}

Here's what I did using just vanilla JS:
function commonDifferentProperties(objects) {
var common = JSON.parse(JSON.stringify(objects[0]));
var unmatchedProps = {};
for (var i = 1; i < objects.length; i++) {
for (var prop in objects[i]) {
checkProps(objects[i],common,prop);
}
for (var commProp in common) {
checkProps(common,objects[i],commProp);
}
}
console.log(common); // this is all the matched key/value pairs
console.log(unmatchedProps); // this is all the unmatched keys
return { common: common, different: unmatchedProps };
function checkProps(source, target, prop) {
if (source.hasOwnProperty(prop)) {
var val = source[prop];
if (!target.hasOwnProperty(prop) || target[prop] !== val) {
unmatchedProps[prop] = true; // note: you could extend this to store values, or number of times you found this key, or whatever
delete common[prop];
}
}
}
}
http://jsfiddle.net/TwbPA/
So I copy the first object and use that to keep track of keys and values that are common. Then I iterate through all the other objects in your array and first look through all the key/values in the common object and compare to the current, deleting any missing properties from the common object if they are not in the current one, then I do the reverse to catch any properties in the current object that aren't in the common (or are in the current, but have the wrong value).

Edit
Sorry, i was in a hurry and didn't had enough time to think about it.
Indeed, there's no need for a sort. I was thinking using a binary algorithm or something..
Here, the updated code without the sort. Console.time() gave me '3ms'.
I'm doing similar to Bergi's solution, but instead of collecting all apparant properties i search for the element that has the fewest amount of properties. This reduces the amount of iterations on the second loop.
I've based the code on the following:
if object X has a property the selected object doesn't have, then it isn't a common property!
Thus the selected object has all common properties + extra's.
The selected object has the fewest properties, thus the iterations of validating is less.
http://jsfiddle.net/kychan/cF3ne/1/
// returns the common properties of given array.
function getCommonProps(objects)
{
// storage var for object with lowest properties.
var lowest = {obj:null, nProperties:1000};
// search for the object with lowest properties. O(n).
for (var j in objects)
{
var _nProp = Object.keys(objects[j]).length;
if (_nProp < lowest.nProperties)
lowest = {obj:objects[j], nProperties:_nProp};
}
// var that holds the common properties.
var retArr = [];
// The object with the fewest properties should contain common properties.
for (var i in lowest.obj)
if (isCommonProp(objects, i)) retArr.push(i);
return retArr;
}
// Checks if the prop exists in all objects of given array.
function isCommonProp(arr, prop)
{
for (var i in arr)
{
if (arr[i][prop]===undefined)
return false;
}
return true;
}
console.time('getCommonProps()_perf');
console.log(getCommonProps(objects));
console.timeEnd('getCommonProps()_perf');

Here's another approach that uses reduce() and transform():
_.reduce(objects, function(result, item) {
if (_.isEmpty(result)) {
return _.assign({}, item);
}
return _.transform(item, function(common, value, key) {
if (result[key] === value) {
common[key] = value;
}
}, {});
}, {});

Related

javascript - search for string in array of objects and return array

I would like to write a function that will search the fields of objects in an array for a specific string, adding this object to a new array if the string is found in any of the object's fields. I've gotten my function to work, but was having the issue of the new list containing multiple copies of the objects which contain multiple copies of the string being searched for. I know this is because I've looped it so that each field it finds the string in, it will add the object once more to the new array. However, I wasn't sure of what alternative way I could go about writing the function to add the object only once, regardless of how many of its fields have matched with the string being searched for. This is my function:
function search (keyword, array){
var newArray = [];
for(let i = 0; i < array.length; i++) {
for (key in array[i]) {
if(array[i][key].includes(keyword)){
newArray.push(array[i]);
}
}
}
return newArray;
}
An example of where the output is problematic is if I do:
console.log(search('yes', myArray))
And if myArray contains an object in which 'yes' appears in 3 different fields, it will add this object to newArray 3 times.
Improved version of Danny Buonocore code.
No accidental global variables.
Uses forEach to iterate over the array.
Uses for...of and Object.values() to iterate over the values of the object (using for..in iterates over all non-Symbol, enumerable properties of an object itself and those the object inherits from its constructor's prototype and are cause for many bugs)
"short circuit" the test for adding an object: if a value has matched, there is no need to check the other values. This alone would probably solved your problem, but using a set will prevent duplicates if you have the same object multiple times in your array.
function search (keyword, array){
var result = new Set();
array.forEach( object => {
for (const value of Object.values(object)) {
if ( value.includes(keyword) ) {
result.add(object);
continue; // Don't need to check more on this item.
}
}
});
return Array.from(result);
}
console.log(search("yes", [
{ key1 :"yes", key2:"yes" },
{ key1 :"no", key2:"no" }
]));
You could use a Set, this will prevent duplicates.
function search (keyword, array){
var result = new Set();
for(let i = 0; i < array.length; i++) {
for (key in array[i]) {
if(array[i][key].includes(keyword)){
result.add(array[i]);
}
}
}
return Array.from(result);
}

Accessing a value in an object of unknown name that is stored in an array (JavaScript)

Its hard to give this question a good name. I'll jump right into the example:
var people = [
{
john: {
score: 1
}
},
{
adam: {
score: 2
}
}
];
I need to loop through this array of objects and get the score values, the trick is I don't know the names (john, adam, ...) but I know each contains a score value.
How do I get them? My current code looks like this:
var pplArr = [];
for (i=0; i<people.length; i++) {
for (var key in people[i]) {
pplArr.push(key);
}
}
for (j=0; j<pplArr.length; j++) {
console.log(pplArr[j]);
//var nameVar = eval(pplArr[j]);
//console.log(people.[j].nameVar.score)
}
The commented section doesn't work since eval() returns undefined otherwise I think it would work. I also tried for (var key in people) and its variations with limited success. Also my two loops look like they are over-complicated, is there no simpler way?
I'm using AngularJS (ionic) thus I would prefer not to use jQuery.
You can use map() and Object.keys().map() will help to iterate over array and Object.keys() helps to gets object keys as an array, get first one from array and get the value.
var people = [{
john: {
score: 1
}
}, {
adam: {
score: 2
}
}];
var res = people.map(function(v) {
return v[Object.keys(v)[0]].score;
});
console.log(res);
Since you don't know if you have more than one person in each object you can recourse in the object looking for all properties named score and return the values in an array like this:
function getAllProperties(o, p){
var properties = [];
Object.keys(o).forEach(function (k) {
if (typeof o[k] === "object") {
properties = properties.concat(getAllProperties(o[k], p));
} else if (k === p) {
properties.push(o[k]);
}
});
return properties;
}
console.log(getAllProperties(people, "score"));
If you want the score of each object in people array, you could do something like this:
for (var i = 0; i < people.length; i++) {
var person = people[i];
for (var key in person) {
for (score in person[key]) {
console.log(person[key][score])
}
}
}

Is there a fast way to select item from array of objects in Javascript?

I have an array:
[
{
key: 'some key',
value: 'some value'
}, {
...
}, ...
]
Is there any simple way to get a certain element of this array without iterating through it and comparing each actual key with desired one?
I currently have a function
var select = function(what, from) {
for (var i in from) {
if (from[i].key == what) {
return from[i];
}
}
return null;
};
I believe there's a better way to handle it.
The short answer is no. There are lots of options to make your code cleaner - like all of the above - but you are still going to have to iterate through them one by one.
You can do 2 things to make it better:
Convert to Map
If you are going to do the search more than once or twice, then convert it to a map of the keys, so at least each subsequent lookup is O(1) instead of O(n). A number of answers suggested that - I use it a lot in my own code - but here is a basic version (there is a shorthand un underscore/lodash):
var i, hash = {};
for (i = 0; i < arr.length; i++) {
hash[arr[i].key] = arr[i].value;
}
Then for all future lookups it is a simple:
var value = hash[key];
Search Algorithms
If it needs to stay as an array for whatever reason, and you have some knowledge about what that array's values will be like, you can use all sorts of search algorithms. Cycling through them one by one is good for an even distribution, but will still be O(n), which will, on average require cycling through half the array (n/2) each time.
But search algorithms are beyond this post...
You were close. This would be the fastest form in this particular case:
var select = function(key, expected, from) {
var i;
for (i = 0; i < from.length; i += 1) {
if (from[i][key] === expected) {
return from[i];
}
}
return null;
};
select('thing', 'foo', [{thing: 'foo'}]);
// => {thing: 'foo'}
But do you require maximum speed? Or would a more elegant, general-purpose solution suit you? If so, use a predicate:
var find = function (array, predicate) {
var i;
for (i = 0; i < array.length; i += 1) {
if (predicate(array[i])) {
return array[i];
}
}
return null;
};
// Find, in an array, an item which passes the following truth test.
find([{thing: 'foo'}], function (item) {
return item.thing === 'foo';
});
// => {thing: 'foo'}
If you don't like writing boilerplate utility code like this, I recommend leveraging a library like lodash. It has a find method already and it's faster and more powerful than anything we could come up with.
Unfortunately not, however, if you alter your structure to use properties it will be much faster. Any other approach will require iteration over the array and will therefore always be less efficient than the below.
var keyValueObj = {
someKey: 'someValue',
nextKey: 'nextValue'
}
// represents 'someValue'
keyValueObj['someKey']
If you're using modern browsers, this should do the magic:
function include(arr,obj) {
return (arr.indexOf(obj) != -1);
}
or in jquery
$.inArray(value, array)
In response to your comment, check this link, this will also address your problem in the comment.
If your keys are strings use them as object properties instead of an array of objects
If your keys are objects use Map()
You can refactor your array into a map, which is, by design, good for quick and effective lookup:
{
'some key': {
value: 'some value'
},
'some other key': {
value: 'some other value'
},
}
Then your select function would be as short as
var select = function(what, from) {
return from[what];
};
If you expect return value of the select() to still have the .key property (which is redundant, as the caller already knows it as what), it is easy to achieve by either keeping the key property in map elements, or auto-adding in in select() before returning.
If you need to run this function very often, I would recommend creating an index:
var yourItemList = [{...}],
select = (function (items) {
var i = 0,
l = items.length,
preparedItems = {};
for (; i < l; ++i) {
preparedItems[items[i].key] = items[i].value;
}
return function (key) {
return preparedItems[key];
};
}(yourItemList));
This way you only iterate once on the item list. After that every select('theKeyYouNeed') just uses the mapped "index".
You can filter array. It is build in Array method so you don't need to declare other helper functions
var arr = [
{
key: 'some key',
value: 'some value'
}, {
key: 'some key1',
value: 'some value'
}
];
arr = arr.filter(function(item) {
return item.key === 'some key'
});
Now arr has only first object (because its key equal to 'some key'). Object that you find is arr[0].
You can use find() instead of filter() when you need just one object. Note, that find() is part of ES6 and has no support in all major browsers

Getting first object from javascript litteral

Lets say I have this object here:
var items = [
{name:"Foo"},
{name:"Bar"},
{name:"foo"},
{name:"bar"},
{name:"foobar"},
{name:"barfoo"}
];
Since it only has one item in each object, I want to just return a list of them.
I tried this:
var getSingle = function(rows){
var items = [];
//This should only return one column
for (var i = 0; i < rows.length; i++) {
var r = rows[i];
var c = 0;
for (var n in r) {
if(c == 0)
items.push(r[n]);
c += 1;
}
}
return items;
}
But it doesn't seem to work. Any thoughts?
PS. name could be anything.
I used a different approach than the others, because I make two assumptions:
1/ you do not know the name of the key, but there is only one key for every item
2/ the key can be different on every item
I will give you a second option, with the second assumption as: 2/ all item have only one key but that's the same for all of them
First Options :
var items = [
{name:"Foo"},
{name:"Bar"},
{name:"foo"},
{name:"bar"},
{name:"foobar"},
{name:"barfoo"}
];
// object keys very simple shim
Object.keys = Object.keys || function(o) {
var result = [];
for(var name in o) {
if (o.hasOwnProperty(name))
result.push(name);
}
return result;
};
// function to get the value of every first keys in an object
// just remember that saying "first key" does not make real sense
// but we begin with the assumption that there IS ONLY ONE KEY FOR EVERY ITEM
// and this key is unknown
function getFirstKeysValues(items) {
var i = 0, len = items.length, item = null, key = null, res = [];
for(i = 0; i < len; i++) {
item = items[i];
key = Object.keys(item).shift();
res.push(item[key]);
}
return res;
}
console.log(getFirstKeysValues(items)); //["Foo", "Bar", "foo", "bar", "foobar", "barfoo"]
Second options will use a map, because we believe that every child possess the same key (I wouldn't use this one, because I do not like .map that much - compatibility):
var items = [
{name:"Foo"},
{name:"Bar"},
{name:"foo"},
{name:"bar"},
{name:"foobar"},
{name:"barfoo"}
];
// object keys very simple shim
Object.keys = Object.keys || function(o) {
var result = [];
for(var name in o) {
if (o.hasOwnProperty(name))
result.push(name);
}
return result;
};
// function to get the value of every first keys in an object
// just remember that saying "first key" does not make real sense
// but we begin with the asumption that there IS ONLY ONE KEY FOR EVERY ITEM
// and this key is unknown but the same for every child
function getFirstKeysValues(items) {
var key = items.length > 0 ? Object.keys(items[0]).shift() : null;
items = items.map(function (item) {
return item[key];
});
return items;
}
console.log(getFirstKeysValues(items));
This is usually accomplished using the map method, see the documentation here.
var justNamesArray = items.map(function(elem) { return elem.name});
The documenation page also includes a useful shim, that is a way to include it in your code to support older browsers.
Accompanying your request in the edit, if you would just like to get those that contain this property there is a nifty filter method.
var valuesWithNamePropert= items.filter(function(elem) { return elem.hasOwnProperty("name")});
You can chain the two to get
var justNamesWhereContains = items.filter(function(elem) { return elem.hasOwnProperty("name")}).
.map(function(elem) { return elem.name});
This approach (mapping and filtering), is very common in languages that support first order functions like JavaScript.
Some libraries such as underscore.js also offer a method that does this directly, for example in underscore that method is called pluck.
EDIT: after you specific that the property can change between objects in the array you can use something like:
var justReducedArray = items.map(function(elem) { for(i in elem){ return elem[i]}});
your var items = [] is shadowing your items parameter which already contains data. Just by seeing your code I thought that maybe your parameter should be called rows
If you're in a world >= IE9, Object.keys() will do the trick. It's not terribly useful for the Array of Objects, but it will help for the iteration of the Array (you would use Array.forEach to iterate the array proper, but then you would use the Object.keys(ob)[0] approach to get the value of the first property on the object. For example:
var someArr = [{ prop1: '1' },{ prop2: '2' },{ prop3: '3' }];
var vals = [];
someArr.forEach( function(obj) {
var firstKey = Object.keys(obj)[0];
vals.push(obj[firstKey]);
});
//vals now == ['1','2','3']
Obviously this isn't null safe, but it should get you an array of the values of the first property of each object in the original array. Say that 3 times fast. This also decouples any dependency on the name of the first property--if the name of the first property is important, then it's a trivial change to the forEach iteration.
You can override the Array.toString method for items, so using String(items) or alert(items) or items+='' will all return the string you want-
var items = [{name:"Foo"}, {name:"Bar"},{name:"foo"},
{name:"bar"},{name:"foobar"},{name:"barfoo"}];
items.toString= function(delim){
delim=delim || ', ';
return this.map(function(itm){
return itm.name;
}).join(delim);
}
String(items)
/* returned value: (String)
Foo, Bar, foo, bar, foobar, barfoo
*/
instead of the default string-'[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]'

Is array both associative and indexed?

Can an array in JavaScript be associative AND indexed?
I'd like to be able to lookup an item in the array by its position or a key value.
There are no such things as associative arrays in Javascript. You can use object literals, which look like associative arrays, but they have unordered properties. Regular Javascript arrays are based on integer indexes, and can't be associative.
For example, with this object:
var params = {
foo: 1,
bar: 0,
other: 2
};
You can access properties from the object, for example:
params["foo"];
And you can also iterate over the object using the for...in statement:
for(var v in params) {
//v is equal to the currently iterated property
}
However, there is no strict rule on the order of property iteration - two iterations of your object literal could return the properties in different orders.
After reading the Wikipedia definition of associative array, I'm going to break with traditional JavaScript lore and say, "yes, JavaScript does have associative arrays." With JavaScript arrays, you can add, reassign, remove, and lookup values by their keys (and the keys can be quoted strings), which is what Wikipedia says associative arrays should be able to do.
However, you seem to be asking something different--whether you can look up the same value by either index or key. That's not a requirement of associative arrays (see the Wikipedia article.) Associative arrays don't have to give you the ability to get a value by index.
JavaScript arrays are very closely akin to JavaScript objects.
arr=[];
arr[0]="zero";
arr[1]="one";
arr[2]="two";
arr["fancy"]="what?";
Yes, that's an array, and yes, you can get away with non-numeric indices. (If you're curious, after all this, arr.length is 3.)
In most cases, I think you should stick to numeric indices when you use arrays. That what most programmers expect, I think.
The link is to my blog post about the subject.
Native JS objects only accept strings as property names, which is true even for numeric array indices; arrays differ from vanilla objects only insofar as most JS implementations will store numerically indexed properties differently (ie in an actual array as long as they are dense) and setting them will trigger additional operations (eg adjustment of the length property).
If you're looking for a map which accepts arbitrary keys, you'll have to use a non-native implementation. The script is intended for fast iteration and not random-access by numeric indices, so it might nor be what you're looking for.
A barebones implementation of a map which would do what you're asking for could look like this:
function Map() {
this.length = 0;
this.store = {};
}
Map.prototype.get = function(key) {
return this.store.hasOwnProperty(key) ?
this.store[key] : undefined;
};
Map.prototype.put = function(key, value, index) {
if(arguments.length < 3) {
if(this.store.hasOwnProperty(key)) {
this.store[key].value = value;
return this;
}
index = this.length;
}
else if(index >>> 0 !== index || index >= 0xffffffff)
throw new Error('illegal index argument');
if(index >= this.length)
this.length = index + 1;
this[index] = this.store[key] =
{ index : index, key : key, value : value };
return this;
};
The index argument of put() is optional.
You can access the values in a map map either by key or index via
map.get('key').value
map[2].value
var myArray = Array();
myArray["first"] = "Object1";
myArray["second"] = "Object2";
myArray["third"] = "Object3";
Object.keys(myArray); // returns ["first", "second", "third"]
Object.keys(myArray).length; // returns 3
if you want the first element then you can use it like so:
myArray[Object.keys(myArray)[0]]; // returns "Object1"
The order in which objects appear in an associative javascript array is not defined, and will differ across different implementations. For that reason you can't really count on a given associative key to always be at the same index.
EDIT:
as Perspx points out, there aren't really true associative arrays in javascript. The statement foo["bar"] is just syntactic sugar for foo.bar
If you trust the browser to maintain the order of elements in an object, you could write a function
function valueForIndex(obj, index) {
var i = 0;
for (var key in obj) {
if (i++ == index)
return obj[key];
}
}
var stuff = [];
stuff[0] = "foo";
stuff.bar = stuff[0]; // stuff.bar can be stuff["bar"] if you prefer
var key = "bar";
alert(stuff[0] + ", " + stuff[key]); // shows "foo, foo"
I came here to wanting to know if this is bad practice or not, and instead found a lot of people appearing not to understand the question.
I wanted to have a data structure that was ordered but could be indexed by key, so that it wouldn't require iteration for every lookup.
In practical terms this is quite simple, but I still haven't read anything on whether it's a terrible practice or not.
var roygbiv = [];
var colour = { key : "red", hex : "#FF0000" };
roygbiv.push(colour);
roygbiv[colour.key] = colour;
...
console.log("Hex colours of the rainbow in order:");
for (var i = 0; i < roygbiv.length; i++) {
console.log(roygbiv[i].key + " is " + roygbiv[i].hex);
}
// input = "red";
console.log("Hex code of input colour:");
console.log(roygbiv[input].hex);
The important thing is to never change the value of array[index] or array[key] directly once the object is set up or the values will no longer match. If the array contains objects you can change the properties of those objects and you will be able to access the changed properties by either method.
Although I agree with the answers given you can actually accomplish what you are saying with getters and setters. For example:
var a = [1];
//This makes a["blah"] refer to a[0]
a.__defineGetter__("blah", function(){return this[0]});
//This makes a["blah"] = 5 actually store 5 into a[0]
a.__defineSetter__("blah", function(val){ this[0] = val});
alert(a["blah"]); // emits 1
a["blah"] = 5;
alert(a[0]); // emits 5
Is this what you are looking for? i think theres a different more modern way to do getters and setters but cant remember.
The tide has changed on this one. Now you can do that... and MORE! Using Harmony Proxies you could definitely solve this problem in many ways.
You'll have to verify that your targeted environments support this with maybe a little help from the harmony-reflect shim.
There's a really good example on the Mozilla Developer Network on using a Proxy to find an array item object by it's property which pretty much sums it up.
Here's my version:
var players = new Proxy(
[{
name: 'monkey',
score: 50
}, {
name: 'giraffe',
score: 100
}, {
name: 'pelican',
score: 150
}], {
get: function(obj, prop) {
if (prop in obj) {
// default behavior
return obj[prop];
}
if (typeof prop == 'string') {
if (prop == 'rank') {
return obj.sort(function(a, b) {
return a.score > b.score ? -1 : 1;
});
}
if (prop == 'revrank') {
return obj.sort(function(a, b) {
return a.score < b.score ? -1 : 1;
});
}
var winner;
var score = 0;
for (var i = 0; i < obj.length; i++) {
var player = obj[i];
if (player.name == prop) {
return player;
} else if (player.score > score) {
score = player.score;
winner = player;
}
}
if (prop == 'winner') {
return winner;
}
return;
}
}
});
console.log(players[0]); // { name: 'monkey', score: 50 }
console.log(players['monkey']); // { name: 'monkey', score: 50 }
console.log(players['zebra']); // undefined
console.log(players.rank); // [ { name: 'pelican', score: 150 },{ name: 'giraffe', score: 100 }, { name: 'monkey', score: 50 } ]
console.log(players.revrank); // [ { name: 'monkey', score: 50 },{ name: 'giraffe', score: 100 },{ name: 'pelican', score: 150 } ]
console.log(players.winner); // { name: 'pelican', score: 150 }
The latest MDN documentation makes it quiet clear that Array index must be integers.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
let arr=[];
arr[0]="zero";
arr[1]="one";
arr[2]="two";
arr["fancy"]="what?";
//Arrays cannot use strings as element indexes (as in an associative array) but must use integers.
//Setting non-integers using bracket notation will not set an element to the Array List itself
//A non-integer will set a variable associated with that ARRAY Object property collection
let denseKeys = [...arr.keys()];
console.log(denseKeys);//[ 0, 1, 2 ]
console.log("ARRAY Keys:"+denseKeys.length);//3
let sparseKeys = Object.keys(arr);
console.log(sparseKeys);//[ '0', '1', '2', 'fancy' ]
console.log("Object Keys:"+sparseKeys.length);//4
const iterator = arr.keys();
for (const key of iterator) {
console.log(key);//0,1,2
}
Yes.
test = new Array();
test[0] = 'yellow';
test['banana'] = 0;
alert(test[test['banana']]);

Categories