I am pushing items into an array but the script becomes unresponsive? - javascript

I'm trying to add an array's members back to itself using a for loop.
Why does this code cause an unresponsive script?
var magicarray = {
arraymemeber: [1, 2, 3, 4, 5],
duplicate: function () {
for (var i = 0; i < this.arraymemeber.length; i++) {
this.arraymemeber.push(this.arraymemeber[i]);
};
}
};
console.log(magicarray.duplicate());

Though I'm not sure why you want this, to avoid an infinite loop that you currently have get the length first and iterate only over the original length of the array.
var magicarray = {
arraymemeber: [1,2,3,4,5],
duplicate: function() {
var length = this.arraymemeber.length;
for (var i = 0; i < length; i++) {
this.arraymemeber.push(this.arraymemeber[i]);
};
}
};
console.log(magicarray.duplicate());

Because you're pushing new items in as you iterate, and your condition is based on the current .length, causing an infinite iteration (or at least as high as the .length will be allowed to go).
If you wanted to "double" the Array, you don't need a loop. You can do this:
this.arraymember.push.apply(this.arraymember, this.arraymember)
So your object would be:
var magicarray = {
arraymemeber: [1, 2, 3, 4, 5],
duplicate: function () {
this.arraymember.push.apply(this.arraymember, this.arraymember)
}
};

Every time you go around the loop, you put an item onto the array. This increases its length by 1.
Since this.arraymemeber.length increases at the same rate as i, you never get to the end of the loop.

Because in each iteration you're adding a new element to the element you're iterating over.
The i < this.arraymemeber.length check is made at the end of each iteration. The length of the array isn't cached in any way.
To prevent an infinite loop, use
for (var i = 0, len = this.arraymemeber.length; i<len; i++) {
... instead.

Just do this:
this.arraymemeber = this.arraymemeber.concat(this.arraymemeber);

Related

Trying to understand why my function won't remove more than one instance of the value arguments[i] from newArr [duplicate]

This question already has answers here:
How to filter an array from all elements of another array
(24 answers)
Closed 8 months ago.
function destroyer(arr) {
const newArr = [...arguments[0]]
for(let i = 0; i < newArr.length; i++){
for(let j = 1; j < arguments.length; j++){
if(arguments[j] == newArr[i]){
newArr.splice(i,1)
console.log(newArr)
}
}
}
}
destroyer([3, 5, 1, 2, 2], 3, 5, 2);
New JS learner here.
Working on a problem that is supposed to look through the first arg in destroyer which will be an array and remove the elements that match the arguments following the array.
Results are [1,2] in the console output. Intended results are [1] with the given parameters Upon further testing it seems like the destroyer function is only removing the first instance of any value that it matches in newArr. If I take the second instance of '2' out of the test set it behaves as intended. I'm trying to understand what in my logic here is wrong. I've tried several different iteration patterns and can't seem to see what the problem is.
Thanks for any help!
I am going to link a few other answers here is this seems to be a fairly common question. The gist is that you are iterating over the live array while removing items from that array resulting in potentially skipping items.
How to iterate over an array and remove elements in JavaScript
Remove multiple elements from array in Javascript/jQuery
Alternatively you could also the filter method to help remove multiple values:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Try this:
function destroyer(arr) {
const newArr = [...arguments[0]]
for(let i = newArr.length - 1; i >= 0; i--){
for(let j = 1; j < arguments.length; j++){
if(arguments[j] == newArr[i]){
newArr.splice(i,1)
console.log(newArr)
}
}
}
}
This is an array pointer issue.
when i = 3 and j = 3, the function will match arguments[3] == newArr[3].
At this moment, newArr will be removed 1 element which is the first 2, and then the newArr becomes an new array that is [3,5,1,2].
The next index i is 4 which doesn't exist in the new newArr. So, the function will return and finish. That's why you get [3,5,1,2].
function destroyer (arg) {
if(!Array.isArray(arg)) return arg;
return arg.filter(x => !Array.prototype.slice.call(arguments, 1).includes(x))
}
It is because newArr is getting shorter as you splice it through your loops and the loop itself is also shortened.
see this probably your solution

how to find an almost increasing sequence Array

I have had an algorithm problem below:
"Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Example
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3]."
My code (for Javascript) was:
function almostIncreasingSequence(sequence) {
var count =0;
for (i =0 ; i<sequence.length-1 ; i++){
if (sequence[i+1]<=sequence[i]){
count++;
}
}
return count <2;
}
However if in the case of sequence =[1,2,3,4,3,4,5]
My code will be wrong;
Please explain to me an algorithm that can be used to solve this problem.
And also please explain in step by step so that I can understand.
Sorry for not being clear as it is my first question here.
This may help.
function almostIncreasingSequence(sequence) {
var exists = false; // Assume the sequence returns false by default
var mainSequence = sequence.slice(); // Clone sequence so that we can use it again
m_seq: // The name of the first loop, so that we can exit from it
for (var i = 0; i < mainSequence.length; i++) { // Loop through the array
sequence.splice(i,1); // Remove an item from the array
s_seq: // The name of the loop, so that we can exit from it
for (var j = 0; j < mainSequence.length-1; j++) { // Loop through sliced array, to find an increasing sequence
if (sequence[j+1] <= sequence[j]) { // Check if next is smaller
exists = false; // if so define false
break s_seq; // exit from the loop
}
exists = true; // if the loop has not been interrupted, return true
}
sequence = mainSequence.slice(); // Reassign the main sequence to be used again.
//console.log('s',mainSequence);
if (exists) {break m_seq;} // İf condition is met, why bother to stay in the loop???
}
return exists;
}
var testing = [1,2,3,4,3,4,5];
var testingAgain = [1,2,3,4,3,7,9];
var testingFinal = [1,1];
// almostIncreasingSequence(testing);
console.log(almostIncreasingSequence(testing));
console.log(almostIncreasingSequence(testingAgain));
console.log(almostIncreasingSequence(testingFinal));

Side effects when async operating on arrays

I'm learning node.js atm, now I'm asking myself:
How "threadsafe" are normal Arrays?
Example:
var myArr = ["Alpha", "Beta", "Gamma", "Delta"];
ee.on('event', function(itemString) {
//Loop over an Array that could change its length while looping through
for(var i=0; i<myArr.length; i++) {
// delete the item out of the array
if(myArr[i] == itemString)
myArr.splice(i,1);
}
});
If multiple of the Events are fired on the ee-Object, is there a chance, that the for Loop will fail because the indexes are already spliceed away?
Or said different: Is a way to ensure that the loop won't skip or fail because any elements that may be deleted by another callback call of the same event?
THX :)
node.js is single threaded and it does not interrupts sync execution.
Still, you're modifying the array while iterating it by its length which may lead to skipping elements.
Also, your event is not prepared to be fired twice for the same array element.
I think we've covered the threading issue well, but you really should still address the loop. For an example of the "skipping" problem I'm talking about, try this:
var a = [1, 2, 3, 4, 5];
for (var i = 0; i < a.length; i++) {
console.log(a[i]);
if (a[i] === 2) {
a.splice(i, 1);
}
}
Output:
1
2
4
5
Notice how the number 3 is never even seen by this loop.
One common way to fix this kind of loop so you can safely delete elements of the array while iterating over it is to go backwards:
var a = [1, 2, 3, 4, 5];
for (var i = a.length - 1; i >= 0; i--) {
console.log(a[i]);
if (a[i] === 2) {
a.splice(i, 1);
}
}
Output:
5
4
3
2
1
Notice that we see all the elements of the array this way.

When looping through values of a JS array, and I remove value, do I need to use while instead of for?

var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
for(var i = 0; i < myArray.length; i++){
if(isOdd(myArray[i])){
myArray.splice(i,1);
i--;
}
}
The code above takes an array of arbitrary length and checks each value. If the value of the bit of the array meets an arbitrary condition (in this case if it is odd), then it is removed from the array.
Array.prototype.splice() is used to remove the value from the array, and then i is decremented to account for the rest of the values in the array "moving down" to fill in the gap that the removed value left (so the loop doesn't skip over a value).
However, the for loop ends when i equals the length of the array, which gets shorter as values are removed.
Does the value of myArray.length decrease dynamically as the loop proceeds, or does it save the value at the start of the loop and not update as values are removed? If the latter, what can I do to fix my loop?
Thank you!
myArray.length is changing with the operation on the array. But looping and splicing leads to unwanted results, if not proper padded.
To prevent unnecessary corrections, use a while loop from the end, to keep the rest of the array for processing.
function isOdd(value) {
return value % 2;
}
var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9],
i = myArray.length;
while (i--) {
if (isOdd(myArray[i])) {
myArray.splice(i, 1);
}
}
console.log(myArray);
The length property is read in every iteration, and the splice method does update its value, so it works as you would expect. However, I would say that this is not a good coding practice, a while loop is much more readable, so it should be the obvious choice.
To answer the question directly: you don't have to use while instead of for, but you definitely should.
Use Array.filter instead
var myArray = [1,2,3,4,5,6,7,8,9];
myArray=myArray.filter(function(item,index) {
return !(item % 2);
})
console.log(myArray)
This is where you'd want to use Array.prototype.filter() if you don't absolutely HAVE to modify the original array, in-place.
As you suspect, the .length property of the array is being updated every time you splice(). The filter() method was built for exactly this sort of operation.
var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
var filteredArray = myArray.filter(function(item){
return !isOdd(item);
});
console.log(filteredArray);
A more concise version of the above code:
var myArray = [1,2,3,4,5,6,7,8,9];
function isEven(value){
return value % 2 === 0;
}
var filteredArray = myArray.filter(isEven);
console.log(filteredArray);
An even more concise version relying on ES6 arrow syntax:
var myArray = [1,2,3,4,5,6,7,8,9];
var isEven = value => value % 2 === 0;
var filteredArray = myArray.filter(isEven);
console.log(filteredArray);
And, in the event that you absolutely MUST edit the array in-place / use splice() here, I would recommend using Array.prototype.forEach() over a for or while loop. forEach() is another higher order method that allows you to realize the same functionality with less boilerplate. As with most higher order methods/functions, it allows you to focus on defining what you need to do rather than exactly how it needs to be done.
var myArray = [1,2,3,4,5,6,7,8,9];
function isOdd(value){
return value % 2;
}
myArray.forEach(function(c, i, a){
if(isOdd(c)){
a.splice(i,1);
}
})
console.log(myArray);
You can use both of them and it's depends on which one you like. if you prefer to use while loop then Nina's answer looks good and if you want to use for loop then consider to manage counter changes by yourself completely or when the length changes:
function isOdd(value) {
return value % 2;
}
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr1.length;)
isOdd(arr1[i]) ? arr1.splice(i, 1) : i++;
console.log(arr1);
var arr2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < arr2.length; i++)
if (isOdd(arr2[i])) {
arr2.splice(i, 1);
i--;
}
console.log(arr2);

Javascript Arrays - Find Duplicates [duplicate]

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.
Here is my question...
Given an array populated with numbers as a function parameter, produce a resulting array which contains any duplicates number from the array.
For example, given the array [ 1, 2, 4, 4, 3, 3, 1, 5, 3 ] it should return [1, 4, 3]. For extra bonus points return a sorted array.
I am starting out with Javascript - I know the language however, using it in the correct way ( as one should ) I'm still getting to grips with.
My pseudo code for this would be to:
Create an array with the numbers above var numbers = [1, 2, 4, 4, 3, 3, 1, 5, 3];
Then create an empty array named "result" var result = [];
Create a for loop that goes through the var numbers to check for duplicates which will then populate the empty array "result" with the duplicates
for (var i = 0;i < numbers.length; i++) {
//This is where I'm stuck...
}
I'm not sure what to do within the for loop to populate the var result and to throw in to the mix... The given array has to be a function parameter which makes sense so you can change the numbers in one place.
Any feedback on my thought process on this so far is greatly appreciated but ultimately I am wanting to learn how to achieve this.
Here is a JSFiddle of my progress so far... http://jsfiddle.net/fbauW/
One way of doing this (and it's not the only way) is by checking for existing elements in the array. Take a look at JavaScript's lastIndexOf function:
http://www.w3schools.com/jsref/jsref_lastindexof_array.asp
It will return -1 if the object does not exist in your array, and if it exists, will return an index of a later position than you are in. So you can use an if statement in your loop that checks whether or not there is another index containing your number, and add it in to your results array IF AND ONLY IF the index you get back != the index you are currently on (if they equal, this means that there is only one of that element in the list).
If you need more help, comment here and I can type some code in!
Good luck!
Array.prototype.contains = function(k) {
for ( var p in this)
if (this[p] === k)
return true;
return false;
};
//this prototype function checks if an element is already in the array or not
//go through all the array and push the element to result if it is not
//this way we can eliminate duplicates
//result will contain the resultant array
function findDuplicates(Numbers) {
var arrayLength = Numbers.length, i, j, result = [];
for (i = 0; i < arrayLength; i++) {
for (j = 0; j < arrayLength; j++) {
if (a[i] == a[j] && i != j && !result.contains(a[i])) {
result.push(a[i]);
}
}
}
return result;
}

Categories

Resources