How to get all children of a subArray in Javascript - javascript

So here's my problem:
So this is what my array looks like, I have shown a fragment of it here (from the console window).
It's overall pretty basic right? Except for it's indexing. As you see the first has value "1" and let's say the second has value "4". As for it's subarrays, these have custom indexes too.
Therefore, the old fashioned:
for(i=0; i<array.length; i++){
someVar = array[i];
//do something
}
won't work.
I get the 1 or 4 from iterating through another array, so don't need to get those.
I want to get all subArrays(not the further nested subArrays, only the second level).
So basicly what I want is something like this(is there something like this?):
array[someIndex].children.forEach(
//do something with **this**
)
To make it more practical for you:
So I know that the first array has index 1. How can I get the values of cat1 and cat2 without knowing it has index 2 (this could also be 6 or 42 for example). In this case, the first array only has one subArray but I would like to make it work for multiple subArrays. (to clarify, select cat1, cat2 from the second level subarray with, in this case, index 2)
Thanks in advance, any help is appreciated!
Evoc

Those aren't arrays. You have
[ { "1": { etc...
which is an array containing an object containing multiple other objects. You can't really use a for(i=...) loop for this, because your keys aren't sequential. You should use a for ... in loop instead:
arr = [{"1":{....}}];
for (i in arr[0]) {
for (j in arr[0][i]) {
console.log(arr[0][i][j]['msg']);
}
}

Use Object.getOwnPropertyNames to get the properties ordered with the integer indices first, from smallest to greatest. Iterate them to get msg1.
var array = {"1":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"jimmy","your_msg":"hello world"},"4":{"3":{"5":{"data":"someData","moreData":"someMoreData"},"msg1":"hello world","msg2":"foo equals bar"},"5":{"8":{"data":"someData","moreData":"someMoreData"},"msg1":"world hello","msg2":"bar equals foo"},"your_name":"billy","your_msg":"foo equals bar"}};
for(let key of Object.getOwnPropertyNames(array[1])) {
if(Object(array[1][key]) !== array[1][key]) break;
console.log('msg1 of "'+key+'": ' + array[1][key].msg1);
}
console.log('your_msg: ' + array[1].your_msg);

The example you showed it's an array with only one index, inside of this index there are nested objects, you could iterate them using the property iterator (foreach). You have to go to the second level tho, since the values you need are there.
for (var key in object) {
for(var anotherKey in object[key]) {
//check for undefined
if(object[key][anotherKey].hasOwnProperty('msg')) {
//code
}
}
}
{ } - declaring objects (literal)
[ ] - declaring arrays

Related

Fast find for indices by ID

I have million of objects each have an unique ID - number.
Each object for making it simple contains name
They objects are being added into array.
Into this array i'm adding and removing objects.
In order to remove object I have the id, and then need to find the index in the array and splice it out.
In my case i have allot of objects and can have allot of removes operations. so in case i have 1000 removes. and all of this objects ids are stored in the end of the array, than i will run over the all 1 million objects till i find them.
Storing the index in the object after adding is not good, because every each remove i need to update the indices of all objects stored after the removed one.
For example removing the first 1000 will cause updating the rest of the 1M-1000 items indices.
My question is, what is the best solution for my problem?
-- UPDATE --
for example: My flat array look like this after adding 1M objects
[ obj1, obj2, obj3, .... obj1000000 ]
I want to remove now the object obj1000000. For finding which index this object
was inserted to i need to run over all the array (or till i found the item) and compare the current item id with my obj1000000 id, and break out from the loop when found. Then remove the item by it's index.
If i would store the index of each object in the object itself after it being added to the array, i would have to update the rest of the objects indices after removing one.
For example: obj1 will contains property index=0, obj2 will have index=1 and so on. To remove obj5 i just get its property index which is 4 and remove it. but now obj6 which has index=5 is incorrect. and should be 4. and obj7 should be 5 and so on. so update must be done.
My SmartArray holds an TypedArray created in some size. And i'm expending it if needed. When push is called. I'm simply set the value in the last item this._array[this.length++] = value; (Checking of course if to expand the array)
SmartArray.prototype.getArray = function () {
return this._array.subarray(0, this.length);
}
SmartArray.prototype.splice = function (index, removeCount) {
if (index + removeCount < this.length) {
var sub = this._array.subarray(index + removeCount, this.length);
this._array.set(sub, index);
} else {
removeCount = this.length - index;
}
this.length -= removeCount;
}
It is working very fast, subarray doesn't create a new array. And set is working very fast as well.
The standard solutions for this problem are
balanced (binary) trees,
hash tables.
They take respectively O(Log(N)) and O(1) operations per search/insertion/deletion on average.
Both can be implemented in an array. You will find numerous versions of them by web search.

for..in loop loops over non-numeric indexes “clean” and “remove”

This is something very basic I might be missing here but I haven't seen such result till now.
I have a for loop where options.headers.length is 3. And in for loop I am dynamically creating a table header. Ideally this loop should run three times for 0 1 and 2 but when I have printed index it's printing 0,1,2,clean and remove. I haven't seen clean and remove as indexes. I know this information is not sufficient enough but if you have any clue please suggest. something might be overriding this is all I am concluded too after my debugging.
for (index in options.headers)
if you don't want to iterate clean and remove then change the loop to:
for (var i=0; i< options.headers.length;i++){
//use i for getting the array data
}
if you use for (index in options.headers) it will iterate for non-numeric keys also.
don use just index (as that is = window.index = global = bad) use var index
(read more here https://www.google.pl/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=globals+javascript+bad)
you have to check does the array has it as own property or maybe its some function (more after answer)
for (var index in options.headers) {
if (options.headers.hasOwnProperty(index) {
// code here
}
}
more about #2:
let's say we have
var array = [0,1,2,3];
and besides that, extending array with function (arrays can have functions in javascript and strings too)
Array.prototype.sayHello = function() {
alert('Hello');
};
then your loop would print sayHello as part of the array, but that's not it's own property, only the arrays
I assume that options.headers is an Array?
This happens when you (or some framework you load) adds methods to the Array prototype. The "for in" loop will enumerate also these added methods. Hence you should do the loop for an array with:
for (var i = 0; i < options.headers.length; i++)
That way you will only get the real values instead of added methods.

getting the amount of properties in an object then getting the last one of them in a for loop

This should be very easy but I don't know how to do it.
I have this object:
var obj = eval(result);
Now I want to know how many properties contains to put it in a loop
var finalAmount = obj.length;
Now I go for the loop
for (var i in obj) {
--- some other code in here
Now here the problem I need to do something when the loop reaches the final property of the obj, so this is what Ive tried:
if (i+1 == finalamount){
//do something
} else {
//do something else
}
so basically using the i as a pointer to compare it to the var that contains how many items there are and when finding the final one of the loop then do something...
In this case i is not necessarily numeric, and so i+1 may not give you the desired results. You should set up a separate counter variable that you increment at the end of each loop iteration.
In your case obj must be an Array. If it is not, i+1 throws error.
The for-in loop does not ensure any sequence order, even it is an Array, it is only used to iterate unordered properties. You need traditional for(index=0;index<length;index++) (if it is an Array)
If your obj variable is an Object instead of Array, you can't get "last property" only with object data structure, it must provide more information (property order).

Javascript Arrays In IE 8 issue

As per what I know, arrays in Javascript is nothing but the combination of methods and objects.
Now my task is to display the values of array (say y_array)
I have used for(x in y_array) and then displayed the value.
In mozilla and in IE its working fine, but in IE it displays the first element of array with index as indexOf and value is indexOf(obj, from) which i dont want.
I tried
if(x!='indexOf') { display the array value ; }
It worked and things were fine but there is extensive use of arrays been displayed and I am looking for some permanent fix rather than this hardcoded one.
Can anyone please help me?
You are not the first mixing up arrays and objects. SO should contain a FAQ for this kind of questions ;)
Let's try to explain things:
An array is a row of values, which can be retrieved using their position in the row. The order of the array values is fixed (and may be reordered).
An object is a variable that contains named properties in the form of key-value pairs. The order of the key-value pairs belonging to an object is arbitrary.
An array looks like: [ 'first', 'second', 'third', ..., 'nth' ]
An object looks like: { first:'firstvalue', second:'secondvalue', ..., nth:'nthvalue' }
The first element of an array is the element with index 0 (so the first position in the row has index value 0). You retrieve it using myArray[0]
An object is unordered, so it has no first element. You retrieve any element from it using myObject.somekey or myObject['somekey'].
For arrays you use a loop iterating through the numbered index until the end of the array is reached:
var i=0, len = myArray.length;
for ( i; i<len; i++ ) {
//do something with >>> myArray[i] <<<
}
For objects you use a loop using the key and the in operator (making sure you are only retrieving user defined properties of the object with the .hasOwnAttribute method):
for ( var key in myObject ){
if (myObject.hasOwnProperty(key)) {
// do something with >>> myObject[key] <<<
}
}
Basically, think of an array as a cupboard with drawers, each containing a value. An object can be imagined as a pile of boxes with stickers on the lid, describing the content of the box. Retrieving something from an object, you ask: is there a box with sticker y in pile x and if so, what's in it? Retrieving something from an array, you ask: please give me the contents of drawer nr x.
Now as to your question: the array you are retrieving values for with a for..in loop contains a user defined method, namely indexOf. Using the object style loop for it, the array is treated as object, and the indexOf key (with value like function(){...} I bet) is shown too. IE That's why it may be better to use a traditional for loop with a numeric index when iterating over arrays.
Why is this only in IE? In modern browsers indexOf is a native method of the Array prototype, and native methods are not shown (unless you loop through their prototype that is). IE < 9 doesn't have a native indexOf method for arrays. Somewhere in the scripting you use the method has been added to the Array prototype as a user defined extension.
Bottom line for your problem: don't use for ... in to loop through the values of an array.
For arrays you should use this for loop:
var y_array = [1,2,3,4];
for (var i = 0; i < y_array.length; i++) {
var value = y_array[i];
// do what you want
alert(i + ': ' + value);
}
For objects (objects are like associative arrays - property: value) use this loop:
var y_array = { prop_1 : "value a", prop_2: "value_2", prop_3: 333 }
for (var key in y_array) {
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}
if there is no value in your json Object like jsobObj = {}. Then you got the indexOf prototype function in side the empty object in IE < 9. (with value like function(){...} I bet) is shown too.
Your can check a condition in side your for Loop. and skip that indexOf.
if(key =='indexOf'){continue;}
E.g :
var jsonObj = { key_1 : "value a", key_2: "value_2", key_3: 333 }
for (var key in y_array) {
if(key == 'indexOf'){continue;} // check if the array contain indexOf
var value = y_array[key];
// do what you want
alert(key + ': ' + value);
}

Question about the for loop in javascript?

In the following code why the variable 'a' refer to the index rather than the value ?
for (var a in Values) {
alert(Values[a]);
}
That's by design. It's trivial to get a value in an array when you know its key, but it's much harder to get a key given a value. Values can be duplicated, so how do you know which key should be used? But a key's unique, so given a key, there's only ever one value to retrieve. So, the for loop will iterate over the keys, and it's trivial to get the associated value.
Think of a JavaScript Array as a normal Object with a special property named length (actually, it a bit more complex). So the for..in loop behaviour is identical as for other objects:
var a = new Array();
a[1] = "a";
alert(a.length); // 2
alert(a[0]); // undefined
a[1000] = "b"
alert(a.length); // 1001
a[-1] = "c";
alert(a[-1]); // c
a.abc="why not";
for(var key in a)
{
alert(key+"="+a[key]);
}
// 1=a
// 1000=b
// -1=c
// abc=why not
Also note that you can have gaps within your array without having to pay the memory price.
There is a for each...in loop that does exactly that - enumerates only values. Coming soon to a browser near you.
for each(var a in Values) {
..
}
For arrays, there is a new function forEach which achieves the same.
someArray.forEach(function(value) {
..
});

Categories

Resources