I need a function to trim a specific number to only 1 repetition in a numbers array.
i can only use .pop, .push .length commands.
If I have array i.e [ 5,4,6,6,8,4,6,6,3,3,6,5,4,8,6,6] I need to trim the duplicates of the the digit 6 to show only one time, so the result would be -
[5,4,6,8,4,6,3,3,6,5,4,8,6].
using only one array.
I have tried to go thru the array with a for loop, and if i find a 6 that comes after another 6 i tried to move all the other elements one step back each time i find a duplicated 6 , array[i] = array [i+1]
I tried looping in a for inside a loop, no luck.
You can loop the array and re-assign values in place, by taking care about whether the current value and the next value are effectively the same and the next one is the targeted one.
Other than that, you need to also handle whether you're at the end of array.
Further explanations can directly be found in the snippet below.
As a final side note, the expected output should rather be:
[5,4,6,8,4,6,3,3,6,5,4,8,6]
instead of
[5,4,6,8,4,6,3,3,6,5,3,8,6]
since slightly before the last 8, in your input, you have a 4, not a 3.
function trimSpecificNumber(arr, target) {
// Define a tracker that will update the array in-place.
var _track = 0;
// Loop over all the elements in the array.
for (var i = 0; i < arr.length; i++) {
// acquire the current and the next value.
var _curr = arr[i], _next = arr[i+1];
// If there is no next value, assign the last element of the array.
if (!_next) arr[_track++] = _curr;
else {
// Otherwise, if the current element is not the same of the next one AND the next one actually isn't the searched needle, assign the current index to the current value (in place).
if (_next === _curr && _next === target) {
// Silence is golden, skip this one.
}
else {
arr[_track++] = _curr;
}
}
}
// Finally, assign the new length of the array, so that next elements will be truncated.
arr.length = _track;
}
var needle = [5,4,6,6,8,4,6,6,3,3,6,5,4,8,6,6];
trimSpecificNumber(needle, 6);
console.log(needle);
In your case iterate the array with a for loop, and if the current item is not
the item to dedupe, or is not identical to the previous, add the item to the current counter, and increment the counter. When the loop ends, change the length of the array to the length of the counter.
function removeSpecificDuplicate(arr, item) {
let counter = 0;
for(let i = 0; i < arr.length; i++) {
if(arr[i] !== item || arr[i] !== arr[i-1]) arr[counter++] = arr[i];
}
arr.length = counter;
}
const arr = [5,4,6,6,8,4,6,6,3,3,6,5,4,8,6,6]
removeSpecificDuplicate(arr, 6);
console.log(arr)
Related
I ran across this strange side effect of array.splice, and distilled the code down to the minimum necessary to recreate. Yes, much of this could be done on one line with array.filter, but I'm interested in whether I've made a mistake or if something else is going on.
var array = [];
for (var i = 0; i < 10; i++) {
array.push({
value: i
});
}
array.forEach(function(item, index, intArray) {
if (item.value % 2 == 1) {
item.odd = true;
} else {
item.odd = false;
}
if (item.odd) {
console.log("Removing " + item.value);
intArray.splice(index, 1);
}
});
console.log(array);
Running this javascript results in the odd elements being removed as expected, but it also removed the item.odd values for items 2, 4, 6, and 8. Removing the intArray.splice line brings back the odd array elements, but it also brings back the item.odd values for all elements.
I've tested this in FF and Chrome. The behavior persists even if only the item is passed into the callback, with the index calculated via array.indexOf, and referencing the array from outside the loop.
I think that when you splice the array at every odd number, the forEach ends up skipping over the next item, which is an even number. So those items don't get modified at all.
var array = [];
for (var i = 0; i < 10; i++) {
array.push({
value: i
});
}
array.forEach(function(item, index, intArray) {
console.log(item); // only prints out 0, 1, 3, 5, 7, 9
if (item.value % 2 == 1) {
item.odd = true;
} else {
item.odd = false;
}
if (item.odd) {
console.log("Removing " + item.value);
intArray.splice(index, 1);
}
});
console.log(array);
In other words, forEach only visits each index once. So say it gets to item 1, which is at index 1. It deletes item 1. Item 2 is now at index 1. But index 1 has already been visited, so it moves on to the item at index 2, which is now item 3.
Since splice is destructive and forEach is not 'live' [it is not automatically updated], the iteration after splice( index, 1 ) will skip over the "old index+1" (the next iteration-index) because it has 'dropped' down to the new index (where the old array element used to be). Using splice to delete array elements (no matter how many elements are deleted) will always create this unexpected 'slippage' from the old index to the new index, and will skip over one array element every time splice is used.
When using splice in a loop to delete array elements I use a for loop with negative iteration. When the array slips down, the for loop will not skip over it because it drops down to the next (negative) iteration:
for ( let i = array.length - 1; i >= 0; i-- ){
// do destructive stuff with splice
}
=> start at the end of the array (don't forget to -1, since arrays are zero-based); continue while i >= 0; and decrement i at each iteration.
I am trying to make a function that takes an array and returns the array with the even numbers before the odd numbers. I figured I'd iterate through the array and check the divisibility of each number with modulo. If it's an even number, I unshift that number to the front of the array and keep going.
I've removed unshift to log that it iterates through so I know the issue isn't with my loop.
/// A = [3,5,6,3,4,2,1]
var sortArrayByParity = function(A) {
for (var x =0; x< A.length;x++) {
if (A[x] % 2 == 0) {
A.unshift(A[x])
}
}
return A;
};
Maximum stack error is occuring.
Because unshift adds an element to the array, thereby increasing its length. Furthermore, once the unshift adds an element to the beginning of the array, the next A[x] is the same as the previous one, as all elements get moved to the right, including x. So the loop never finishes, because the index x never reaches the ever increasing length.
If you need to add elements to an array through which you are iterating with a loop, it's better to do it with push in a loop that counts downwards from length to 0. That way, the loop will never iterate through added elements, and the elements that it will iterate through will not move.
When you unshift an array an element is added to the start of that array and increase the length.
Lets try
let arr = [1];
console.log('arr = ',arr, 'length =', arr.length);
arr.unshift(0);
console.log('arr = ',arr, 'length =', arr.length);
As a result when you find a even number you unshift it to the front but it will also be available in x + 1 position. and as you iterate you will find the same even number in next iteration.
correct implementation would be.
/// A = [3,5,6,3,4,2,1]
var sortArrayByParity = function(A) {
for (var x =0; x< A.length;x++) {
if (A[x] % 2 == 0) {
A.unshift(A[x]);
A.splice(x+1, 1);
}
}
return A;
};
console.log(sortArrayByParity([3,5,6,3,4,2,1]));
You should use both unshift and splice.
I ran across this strange side effect of array.splice, and distilled the code down to the minimum necessary to recreate. Yes, much of this could be done on one line with array.filter, but I'm interested in whether I've made a mistake or if something else is going on.
var array = [];
for (var i = 0; i < 10; i++) {
array.push({
value: i
});
}
array.forEach(function(item, index, intArray) {
if (item.value % 2 == 1) {
item.odd = true;
} else {
item.odd = false;
}
if (item.odd) {
console.log("Removing " + item.value);
intArray.splice(index, 1);
}
});
console.log(array);
Running this javascript results in the odd elements being removed as expected, but it also removed the item.odd values for items 2, 4, 6, and 8. Removing the intArray.splice line brings back the odd array elements, but it also brings back the item.odd values for all elements.
I've tested this in FF and Chrome. The behavior persists even if only the item is passed into the callback, with the index calculated via array.indexOf, and referencing the array from outside the loop.
I think that when you splice the array at every odd number, the forEach ends up skipping over the next item, which is an even number. So those items don't get modified at all.
var array = [];
for (var i = 0; i < 10; i++) {
array.push({
value: i
});
}
array.forEach(function(item, index, intArray) {
console.log(item); // only prints out 0, 1, 3, 5, 7, 9
if (item.value % 2 == 1) {
item.odd = true;
} else {
item.odd = false;
}
if (item.odd) {
console.log("Removing " + item.value);
intArray.splice(index, 1);
}
});
console.log(array);
In other words, forEach only visits each index once. So say it gets to item 1, which is at index 1. It deletes item 1. Item 2 is now at index 1. But index 1 has already been visited, so it moves on to the item at index 2, which is now item 3.
Since splice is destructive and forEach is not 'live' [it is not automatically updated], the iteration after splice( index, 1 ) will skip over the "old index+1" (the next iteration-index) because it has 'dropped' down to the new index (where the old array element used to be). Using splice to delete array elements (no matter how many elements are deleted) will always create this unexpected 'slippage' from the old index to the new index, and will skip over one array element every time splice is used.
When using splice in a loop to delete array elements I use a for loop with negative iteration. When the array slips down, the for loop will not skip over it because it drops down to the next (negative) iteration:
for ( let i = array.length - 1; i >= 0; i-- ){
// do destructive stuff with splice
}
=> start at the end of the array (don't forget to -1, since arrays are zero-based); continue while i >= 0; and decrement i at each iteration.
for (let i = 0; i < arrayItemsLen; i++) {
let uniqueItems = arrayItems.filter(function(item, i, arrayItems) {
return i == arrayItems.indexOf(item);
});
}
This method retrieves unique items in the arrayItems to uniqueItems array. What I want to do is also get the index numbers of each unique element and assign it to another temp array. I can't find a way to achieve that.
E.g.: arrayItems.indexOf(item) gives the index of each unique element, but then, how do I get that index to the tempArray[i], I guess I need a for loop but I really don't know where to put it.
I would use something like
var uniqueIndices = [],
uniqueValues = [];
for(var i=0; i<array.length; ++i) {
if(uniqueValues.indexOf(array[i]) >= 0) continue;
uniqueIndices.push(i);
uniqueValues.push(array[i]);
}
Basically, it iterates array checking if the current value is already in uniqueValues. If it's there, it does nothing and continues to the next iteration. Otherwise, it adds the value to uniqueValues and the key to uniqueIndices.
Using i == array.indexOf(array[i]) like in your question would also work, but it may be slower because array will be bigger than uniqueValues.
3 hours ago, I asked a question in SO , about deleting a part of an object, so I linked this question to it:
delete a part of object in javascript
but now another problem occurred when I deleted from that array.
I use that object to populate a FlexiGrid. but when I delete an item from that object by following code, instead of delete that item , it sets to undefined :( and flexigrid did not accept it for input data.
for (var i = 0; i < Roomdata.length; i++) {
if(Roomdata[i].id = X) {
delete Roomdata[i];
break;
}
}
For example, imagine I have 3 items in Roomdata like this :
{item1, item2, item3}
When I call this code to delete item2 , Roomdata object looks like this :
{item1, undefined, item3}
and this is a bad format to be accepted by flexigrid as input data
Is there any solution ?
Thanks every body and sorry about my bad syntax (I am new in English)
regards , Foroughi
Walk through the array in reverse order, and use .splice to remove the element.
You have to walk in the reverse order, because otherwise you end up skipping elements See below.
for (var i = Roomdata.length-1; i >= 0; i--) {
if (Roomdata[i].id == X) {
Roomdata.splice(i, 1);
break;
}
}
What happens if you don't walk in the reverse order:
// This happens in a for(;;) loop:
// Variable init:
var array = [1, 2, 3];
var i = 0;
array.splice(i, 1); // array = [2, 3] array.length = 2
// i < 2, so continue
i++; // i = 1
array.splice(i, 1); // i=1, so removes item at place 1: array = [2]
// i < 1 is false, so stop.
// array = [2]. You have skipped one element.
What you have is an Array. You should use the splice() method to remove an element from an array, not by deleteing the element.
for (var i = 0; i < Roomdata.length; i++) {
if(Roomdata[i].id = X) {
Roomdata.splice(i, 1);
break;
}
}
Using splice in spite of delete.
Roomdata.splice(i, 0);
splice attribute removes blank string elements, undefined references, NULLs and FALSEs.
it will solve your problem
To remove all of the elements of an array matching a particular value, you can do this:
// Remove all elements in arr[] matching val
for (let i = 0; i < arr.length; i++) {
if (arr[i] === val) {
arr.splice(i--, 1); // Remove arr[i] and adjust the loop index
}
}
Note that this is a forward scan of the array. The decrement of the loop index is necessary so that the loop does not skip the next element after an element is removed.