I have an array of objects
x = [{id:null},{id:null},{id:null},{id:null}];
Lets say that the values for the array changed
x = [{id:1},{id:3},{id:8},{id:12}];
And i wanted to revert the values to all null,which method will be faster for performance
A) Reconstructing the array again
x=[];
for (var i=0; i<5; i++) {
var obj = {};
obj.id = null;
x.push(obj);
}
B) Resetting the values
for (var i in x) {
x.id = null;
}
Unless you have thousands of elements, you will never notice a difference in performances.
However the second solution is more clear than the first one.
Alternatively, to make it clear x is an array:
for (var i = 0; i < x.length; ++i) {
x[i].id = null;
}
Your B will just add property id to your array and set it's value to 'null'. On top of that, you should not use for in on arrays.
Fastest way would probably be:
var i = x.length;
while(i--){
x[i].id = null;
}
But you wouldn't see the difference unless your array has thousands of elements, and probably shouldn't even try to optimize it for the performance, before you're sure that you need to. In most use cases readability of the code will be much more important than a few fragments of a second that you could gain.
Related
I have an assignment which i need to sole but i am really stuck and can't make a progress. The assignment consist in an array of elements like this
const appleHolderLine = ['Rome', 'Ambrosia', 'Rome', 'RedDelicious', 'Akane','RedDelicious', 'SweeTango', 'RedDelicious', 'RedDelicious', 'Opal', 'Winesap', 'RedDelicious', 'Empire', 'RedDelicious', 'Liberty'];
Firstly it is needed to declare a variable lineCount which count for every element of the array and a reference to an object called appleMap.
Than the challenge consist in looping through the array and the elements of the array would be the object keys with no duplicates and the values would be an array of idexes of the specific element place of the array. To give an example how it should look like:
Example:
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
console.log (lineCount, appleMap)
Should Log:
5, {'GreenApples':[0], 'RedDelicious': [1,4], 'OrangeApples':[2], 'PurpleApples': [3]}
My progress so far
var lineCount = 0;
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
lineCount++;
// if element in the array exist in the array
appleMap[appleHolderLine[i]] = [i];
}
Could you give me a hint of how to solve this, i am really stuck.
Basically you can create an empty array the first time and keep pushing like below
var lineCount = 0;
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
lineCount++;
if(!appleMap[appleHolderLine[i]])
appleMap[appleHolderLine[i]] = []
appleMap[appleHolderLine[i]].push(i);
}
You could use Array.prototype.reduce which is a more advanced construct javascript provides. Please refer to answer by CodeManiac below for the same.
The above answer is to clarify the basic idea and hint on how you could think
Also, lineCount can be obtained by using appleHolderLine.length directly.
You don't need an extra variable ( Line count ) here, simply loop over the value use, use the index to access value, check if there's nothing present for that key then just initialize it with empty array, push index to the key in each iteration
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
var appleMap = {};
for (let i = 0; i < appleHolderLine.length; i++){
if(!appleMap[appleHolderLine[i]]){
appleMap[appleHolderLine[i]] = []
}
appleMap[appleHolderLine[i]].push(i);
}
console.log(appleMap)
You can simply use reduce
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
let final = appleHolderLine.reduce((op,inp,i)=>{
op[inp] = op[inp] || []
op[inp].push(i)
return op
},{})
console.log(final)
Line count is simply same as length of array, let lineCount = appleHolderLine.length
I suppose, the shortest answer is the functional one.
const appleHolderLine = ['GreenApples', 'RedDelicious','OrangeApples', 'PurpleApples', 'RedDelicious']
result = appleHolderLine.reduce((a,c,i) => { if(a[c]) a[c].push(i); else a[c]=[i]; return a; }, {})
console.log(result)
But I am not sure that you are expected to deliver a functional solution. Still, you might find it useful. The idea is that the reduce method starts with an empty object and iterates through the array. In each iteration, it checks if the current element c is already a field of the accumulator a. If so adds its index i to the specific field, if not, initializes the field with the current element as name and the index as a single-element array as value.
I am now practicing some methods in javascript, like shift(), unshift(), push(), pop(), and I want to write a little function that will take 3 arguments, an array, a start point, an end point. Which is used to cut a part of array out, and then return both the new array and the cut part. Not a useful thing or a big deal, just want to practice javascript.
But I encountered a strange thing, which I don't know why.
Here is the strange part
var a1 = [];
var a2 = [9,8,7,6,5,4,3,2,1];
for(var i=0; i<a2.length; i++){
a1.unshift(a2.shift())
}
So I wrote this code, and the expected result should be
a1 = [1,2,4,5,6,7,8,9]
a2 = []
However, when I run the code, this was what actually happened
a1 = [5,6,7,8,9]
a2 = [4,3,2,1]
It seems like the function was looped not enough time, so I tried to change the a2.length to a integer: 9
which make the code become
var a1 = [];
var a2 = [9,8,7,6,5,4,3,2,1];
for(var i=0; i<9; i++){
a1.unshift(a2.shift())
}
And that worked!
Then I change the approach to this
var a1 = [];
var a2 = [9,8,7,6,5,4,3,2,1]
var aLength = a2.length;
for(var i=0; i<aLength; i++){
a1.unshift(a2.shift())
}
And this worked too!!!
Could anyone tell me why is that ???
And how can I improve the loop?
Thank you very much, really appreciate for your time.
You could easily do this by using while loop
while (a2.length > 0)
{
a1.unshift(a2.shift());
}
The loop condition is re-evaluated for each iteration, and a2.length is constantly changing.
If you want to use its initial value, cache it beforehand:
var n = a2.length;
for (var i = 0; i < n; i++) {
a1.unshift(a2.shift());
}
Javascript Array: Shift() Method
The shift() method is like the pop() method, only it works at the
beginning of the array. The shift() method pulls the first element off
of the given array and returns it. This alters the array on which the
method was called.
So when you do a a2.shift() it will actually modify (decrease the number of elements in the array) the array and thus the effect
This question already has answers here:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
(97 answers)
Closed 8 years ago.
var data = localStorage.getItem('oldData').split(" ");
I am accessing localStorage as above and getting an array of values. Some of the elements are repeated in the string value for oldData, for example:
apples oranges apples apples
I want data to have only two elements apples and oranges. How can I do this in Javascript?
Array.prototype.unique = function(){
return Object.keys(this.reduce(function(r,v){
return r[v]=1,r;
},{}));
}
Strap it on. It's O(n) because using an object just requires you to loop through the array once and assign every value in it as a key, overwriting as you go. This only works when the values are primitives (or you have Harmony WeakMaps). But that's almost always the kind of array you want to do this one so it works out.
For bonus points here's the second best way to do it. This is at minimum twice as fast as the normal double loop answers and is at minimum as good as the ones requiring presorting,
(but still worse than the above hash method which is infinitely faster).
Array.prototype.unique = function(){
return this.filter(function(s, i, a){
return i == a.lastIndexOf(s);
});
}
The reason it beats every other answer aside from the hash is because it's able to get the benefit of sorting without doing the sorting step. It only searches from the current item forward, and from the other end in reverse, so there will never be a case where two items are checked against each other twice, and there will never be an unnecessary comparison done because it always quits at the very minimum amount of work needed to make a final decision. And it does all of this with the minimum possible creation of placeholder variables as a bonus.
first is to insert one value in your array by using push
var array = [];
array.push("newvalue");
then the next insertion of value, check if your value is existing in your array using "for loop". then if the value does not exist, insert that value using push() again
Array.prototype.unique = function()
{
var a = [];
var l = this.length;
for(var i=0; i<l; i++)
{
for(var j=i+1; j<l; j++)
{ if (this[i] === this[j]) j = ++i; }
a.push(this[i]);
}
return a;
};
Something like this should do the trick:
uniqueValues = function(array) {
var i, value,
l = array.length
set = {},
copy = [];
for (i=0; i<l; ++i) {
set[array[i]] = true;
}
for (value in set) {
if (set.hasOwnProperty(value)) {
copy.push(value);
}
}
return copy;
}
This is what I have used finally
var data = localStorage.getItem('oldData').split(" ");
var sdata = data.sort();
var udata = [];
var j = 0;
udata.push(sdata[0]);
for (var i = 1; i < data.length - 1; i += 1) {
if (sdata[i] != udata[j]) {
udata.push(sdata[i]);
j++;
}
}
In the following code sample i get a strange behavior
var data = ['xxx', 'yyy'];
for (var i in data)
{
var a = i;
var b = data[i];
}
The two first iterations works just fine. I get index "0" and "1" in i, but then it loops one extra time and now the i is "sum". Is this by design or what is this extra iteration used for? The result in my case is always empty and it messes up my code. Is there a way to not do his extra loop?
BR
Andreas
It looks like you (or some other code you've included) have added extra properties onto the Array prototype. What you should be doing is checking to see whether the object you're iterating over actually has that property on itself, not on its prototype:
for (i in data) {
if (data.hasOwnProperty(i)) {
a = i;
b = data[i];
}
}
That said, you should never use for .. in on arrays. Use a regular for loop.
See here for more information: http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
You are looping through an Array, not through an Object. For arrays it's better to use:
for (var i=0; i<data.length; i=i+1){
/* ... */
}
In your loop every property of the Array object is taken into account. That makes the for ... in loop for array less predictable. In your case it looks like sum is a property (method) that's added to Array.prototype elsewhere in your code.
There are more ways to loop through arrays. See for example this SO-question, or this one
Just for fun, a more esoteric way to loop an array:
Array.prototype.loop = function(fn){
var t = this;
return (function loop(fn,i){
return i ? loop(fn,i-1).concat(fn(t[i-1])) : [];
}(fn,t.length));
}
//e.g.
//add 1 to every value
var a = [1,2,3,4,5].loop(function(val){return val+1;});
alert(a); //=> [2,3,4,5,6]
//show every value in console
var b = [1,2,3,4,5].loop(function(val){return console.log(val), val;});
Here's a way to safely iterate.
var data = ['xxx', 'yyy'];
for (var i = 0; i < data.length; i++)
{
var a = i;
var b = data[i];
}
What you are getting is an method coming from extending the Array object, I guess you are using some library where is something like
Array.prototype.sum = function () {...};
Perhaps setting data like this would work better: var data = {0:'xxx', 1:'yyy'};
First of all data is an object. Try to add console.log(a); and console.log(b); inside your loop and you'll see.
Consider the following code:
var _test1 = [];
_test1[88] = 'sex';
_test1[1999990] = 'hey';
for(i = 0, length = _test1.length; i < length; i++){
if(_test1[i] == 'hey'){
alert(_test1.length);
}
}
this takes a lot of time, and there are only 2 values.
Is there any way to be faster? Even by using another system that index objects by a number and then loop them fast?
You can use a for / in loop:
for (var i in _test1) {
if (!_test1.hasOwnProperty(i) || isNaN(+i)) continue;
if(_test1[i] == 'hey'){
alert(_test1.length);
}
}
This is exactly what you're looking for; it will only loop over the indices that are actually defined, and will skip any holes in the array.
Have you tried using an Object instead? Numbers should be converted to strings automatically. You would traverse the list with a for...in loop.