Javascript array object arrays - javascript

THis is going to sound like a stupid question but here it goes. I have a js array formatted like so
var locationID = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
I am trying to loop through the array
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
I want to get both elements from the inner array so the ID and location. would I do this by object[0] or object["ID"] for example.
Also is there a more efficient way to do what I need to do like a for each loop or something along those lines.

Use object.ID or object['ID'].
Objects {} in JavaScript are associative, or named arrays. (Also known as a map in many languages. They are indexed by strings (in this case).
Arrays [], are indexed by integral numbers, starting from 0 and counting up to n-1, where n is the length of the array.
If you want to programmatically go through all the (key, value) pairs in each object, you can use this method.
Quotations (String Literals)
To reiterate my comment below about single and double quotes:
If you're talking about inside the [], no [,they're not important]. JavaScript treats single
quotes and double quotes pretty much the same. Both of them denote
string literals. Interestingly, you can use single quotes inside
double quotes or vice-versa: "I wanted to say 'Hello world!'" would be
a (single) valid string, but so would 'But I accidentally said "Goodbye".

This is an optimized loop based from the book of Nicholas Zackas (YAHOO performance chief). I am performing a cached array length to prevent re-evaluation of array length on every iteration of the loop. Please check jsperf.com. Also, native loop is always faster than method based loops jQuery.each and Array.prototype.forEach. This is also supported on browsers below ie8
var currentItem,
locationInfo = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
for (var i = 0, len = locationInfo.length; i < len; i++) {
currentItem = locationInfo[i];
console.log(currentItem.ID);//I prefer this because it shrinks down the size of the js file
console.log(currentItem["ID"]);
}

what you have already will return each of the objects in the JSON as you run the loop. What you need is something like
for(i = 0; i < locationID.length;i++){
var object = {locationID[i].ID, locationID[i].location};
}
Remember properties of objects are accessed by their keys since they are key-value pairs.

For loops are going to be your best bet as far as speed, here's how you'd do it with forEach (IE 9+)
locationID.forEach(function(location, i){
console.log(location['ID'])
console.log(location['location'])
});
jQuery make's it a little easier but runs slower
$.each(array, function(i, item){
});
http://jsperf.com/for-vs-foreach/75
Also here a useful link: For-each over an array in JavaScript?

You can use the forEach method, which make your code more cleaner.
See forEach
locationID.forEach(function(elm){
//Here, elm is my current object
var data = elm;
console.log(data.ID):
console.log(data.location);
});
EDIT :
Then for your second question, you should filter and map methods.
function findNamebyID(id){
//Filter by id and map the data to location
return locationID.filter(function(elm){
return elm.ID === id;
}).map(function(elm){
return elm.location;
})
}

Something as:
var location = locationID.reduce(function(ob, cur) {
ob[cur.ID] = cur.location;
return ob;
}, {});
The result you get is:
Object {ID1: "location1", ID2: "location2", ID3: "location3"}
Meaning you can do:
location.ID1 // location1
location.ID2 // location2
...

an alternative to your loop, would be to use the JavaScript for (.. in ..) since you aren't really using the iterator; it just adds fluff
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
could be written as:
for (item in locationID) {
var object = item;
}

Related

Getting the name of an array under another array

Suppose I have this code:
var simple = {
Cicatrix: ["Rock", "Bottom", "Stunner"],
Yen_Sid: ["Pirate", "Heroes", "Power"],
};
Calling Rock, Bottom, Stunner and etc. is easy.
document.write(simple.Cicatrix[0]);
However, what if i wanted to get the word Cicatrix and Yen_Sid? I want them to be called because I am going to use them as menus.
Also is it possible to have spaces in array names? Like Yen_Sid turns to Yen Sid. Or should I do a .replace?
Yes, you can have spaces in property names, you just need a delimiter around it:
var simple = {
Cicatrix: ["Rock", "Bottom", "Stunner"],
"Yen Sid": ["Pirate", "Heroes", "Power"],
};
However, if you want to loop out the items in a specific order, then you don't want them as object properties, you want them as items in an array. The properties in an object doesn't have a specific order, so when you loop out properties the order depends on the implementation in the browser, and different browsers will give you the properties in different order.
var simple = [
{ name: "Cicatrix", items: ["Rock", "Bottom", "Stunner"] },
{ name: "Yen Sid", items: ["Pirate", "Heroes", "Power"] }
];
To loop through the items and subitems you just need a nested loop:
for (var i = 0; i < simple.length; i++) {
// menu item is in simple[i].name
// subitems are in simple[i].items:
for (var j = 0; j < simple[i].items.length; j++) {
// subitem is in simple[i].items[j]
}
}
Simply use a for loop to go over simple with a replace.
var simple = {
Cicatrix: ["Rock", "Bottom", "Stunner"],
Yen_Sid: ["Pirate", "Heroes", "Power"],
};
for(x in simple)
console.log(x.replace('_',' '));
This allows you to iterate over an object's properties
for (var property in object) {
if (object.hasOwnProperty(property)) {
// do stuff
}
}
It is not possible to have whitespace as you suggest in object notation property names unless you use double quotes like
obj = {"prop 1": [1,2,3]}
var t = obj["prop 1"]
For your first question, getting keys as strings is possible using Object.keys() method. I am not going to write examples here since the documentation I provided earlier has plenty of snippets that shows you how to use it. Other solution would be to use for loop to loop over the keys as Matthew Christianson pointed out in other answer.
And yes, you can have keys that are named with space, but when you're calling them be sure to do it using object.[property] notation, as in:
var x = {
"a b c" : 1234
}
console.log(x["a b c"]); // will log "1234" to Console!
I wouldn't suggest you using names with spaces since your code gets a bit messy using bracket notation, in my opinion. But you can make another object whose keys are keys from your primary object, and values are correctly spelled names, as in:
var names = {
YenSid : "Yen Sid",
SomeName : "Some name",
SomeOtherName : "Some other name"
}
var properObject = {
YenSid = 123,
SomeName = 456,
SomeOtherName = 789
}
And to get a correct name just use names.YenSid
Try this, its an example of how to print out the array to a string.
var text = "";
$.each(simple, function(k) {
text = text + "// " + k + " contains: ";
for ( var i = 0, l = $(this).length; i < l; i++ ) {
text = text + $(this)[i] + ", ";
}
});
console.log(text);

Most efficient and clean way to push a value to an array only if it does not exist yet

Suppose an array named myArray containing several values but no duplicates.
Suppose I want to push a value into it only if it won't lead to duplicates presence.
How I determinate duplicates => by comparing value's id.
I thought about Lodash#uniq to do the trick:
myArray.push(aNewValue);
myArray = _.uniq(myArray,function(item){
return item.id;
});
However, I don't like the reassignment to the array and especially the fact that I have to push before checking...
Is there a more "functional" way to achieve it while being very short?
I don't want to iterate through the array explicitly in order to apply the check.
That's why I attempted to use Lodash.
You can check the presence of an item before adding it :
if(myArray.indexOf(aNewValue) == -1) {
myArray.push(aNewValue);
}
The most efficient way to do this is generally to use an object for uniqueness, because an object can have at most one key of a certain value. However, this is restricted to strings and things that stringify, since only strings can be object keys.
There are two approaches here. If you are using your array often, then you should keep parallel structures - an object for uniqueness check, an array for arrayness of it.
If you don't need your array often, i.e. you want to push a bunch of things and then have an array be unique, you can just use the object, and transform it into an array when you need it (which is somewhat expensive, so you only want to do it once, but still cheaper than manipulating two different structures all the time).
The first approach is illustrated here:
function Set() {
this.presence = {};
this.array = [];
};
Set.prototype.push = function(key, value) {
if (this.presence[key]) return;
this.presence[key] = true;
this.array.push(value);
};
var a = new Set();
a.push(3, { id: 3, value: "SOMETHING" });
a.push(7, { id: 7, value: "SOMETHING ELSE" });
a.push(3, { id: 3, value: "SOMETHING" });
console.log(a.array); // => only 2 elements
The second, here:
function Set() {
this.store = {};
};
Set.prototype.push = function(key, value) {
this.store[key] = value;
};
Set.prototype.array = function() {
var that = this;
return Object.keys(this.store).map(function(key) { return that.store[key]; })
};
...
console.log(a.array()); // note the newly added parentheses :)
Both of these are still cheaper than looking for presence inside the array using indexOf, even more so when you do your own iterating, except very much maybe in case the array is very short.
You could use Array.prototype.some() to find out if the value is already part of the array, e.g.:
if( myArray.some(function (elem) { return elem.id == newValue.id }) )
myArray.push(newValue);
You can't really get away with not looping through the array, though.

get index of element in array if it exists in another array/object

There are two arrays:
itemKeys: [
{
name: "REFOBJTYPE"
},
{
name: "REFOBJKEY"
}
...
]
itemValues: [
{
value: ""
},
{
value: ""
}
]
and an object
ref: {
REFOBJTYPE: 1,
REFOBJKEY: 2,
}
They are fixed and the structure itself cannot be changed.
values of itemValues should be filled with values from ref object,
to get index we have to look up the itemKeys array.
The point of this question: I don't want to use 2 "for" loops to check for each key if it exists in ref. I WANT use JAVASCRIPT specific features like maybe "indexOf", so:
is the ANY OTHER way, rather than TWO FOR-LOOPs to complete this task?
Please don't question why I need this, why don't I like 2 loops. Obviously under any implementation "behind" it will be 2 loops.
I'm not sure if this is what you meant, but if you loop over the itemKeys array, you can easily look up the value associated with the key in the ref object, and then write that out to the itemValues array in one loop.
for (var i = 0; i < itemKeys.length; i++) {
var key = itemKeys[i].name;
var value = ref[key];
itemValues[i].value = value;
}

How to join an associative array into a string

I am trying to do this now and I wonder if there is a "the most used" method to join an associative array (it's values) into a string, delimited by a character.
For example, I have
var AssocArray = { id:0, status:false, text:'apple' };
The string resulted from joining the elements of this object will be
"0, false, 'apple'" or "0, 0, 'apple'"
if we join them with a "," character
Any idea? Thanks!
Object.keys(AssocArray).map(function(x){return AssocArray[x];}).join(',');
PS: there is Object.values method somewhere, but it's not a standard. And there are also external libraries like hashish.
Just loop through the array. Any array in JavaScript has indices, even associative arrays:
var AssocArray = { id:0, status:false, text:'apple' };
var s = "";
for (var i in AssocArray) {
s += AssocArray[i] + ", ";
}
document.write(s.substring(0, s.length-2));
Will output: 0, false, apple
The implementation of functions like Object.map, Object.forEach and so on is still being discussed. For now, you can stick with something like this:
function objectJoin(obj, sep) {
var arr = [], p, i = 0;
for (p in obj)
arr[i++] = obj[p];
return arr.join(sep);
}
Edit: using a temporary array and joining it instead of string concatenation for performance improvement.
Edit 2: it seems that arr.push(obj[p]); instead of incrementing a counter can actually be faster in most of recent browsers. See comments.

JQuery Array To Re-arranged JSON object

I want to covert this javascript Array
[
"Data",
[
"API",
"Apiales",
"Apiaceae",
"Apia",
]
]
to this rearranged json Format
[
{"name":"API","id":"1"},
{"name":"Apiales","id":"1"},
{"name":"Apiaceae","id":"1"},
{"name":"Apia","id":"1"}
]
Thanks
update:
i have tried this
var aNewData =[];
for(i in aData[1]){
var item={};
item.name = aData[1][i];
item.id = "1";
aNewData[i]=item;
}
Where do the ids come from? Test following script, your array is in aData and the result will be in aNewData:
var aNewData = [];
for (var i = 0; i < aData[1].length; i++) {
aNewData.push({
"name": aData[1][i],
"id": 20 + i
});
}
Also see this example.
You might easily transform those data via folding:
var sourceData = ["API","Apiales","Apiaceae","Apia"];
var transformed = sourceData.reduce(function(result, name, index) {
return result.concat({
name: name,
id: 20 + index
});
}, []);
This will give you essentially the same, as the for loop of scessor, but in a more data-centric way.
Think of it like this:
You hold your source data (the array with all those "api*" strings)
You create a fresh resulting array [] (passed as 2nd argument to the reduce), which should be returned as your next result.
Pass an unnamed function to reduce that will be called with 3 arguments, each time it is called, namely result, which is you recently created array, name the value of each of those "api*" strings, and index, which is the index of those strings within the original array.
You look at each of those "api*" strings consecutively and put a new object containing your desired data into it. As result.concat will return the whole array, you just add those
The result array containing all your data will be returned.
But just in case you wanted to be backward compatible with older browsers, I'd recommend using underscore.js for that.

Categories

Resources