I want to remove an element in an array with multiple occurrences with a function.
var array=["hello","hello","world",1,"world"];
function removeItem(item){
for(i in array){
if(array[i]==item) array.splice(i,1);
}
}
removeItem("world");
//Return hello,hello,1
removeItem("hello");
//Return hello,world,1,world
This loop doesn't remove the element when it repeats twice in sequence, only removes one of them.
Why?
You have a built in function called filter that filters an array based on a predicate (a condition).
It doesn't alter the original array but returns a new filtered one.
var array=["hello","hello","world",1,"world"];
var filtered = array.filter(function(element) {
return element !== "hello";
}); // filtered contains no occurrences of hello
You can extract it to a function:
function without(array, what){
return array.filter(function(element){
return element !== what;
});
}
However, the original filter seems expressive enough.
Here is a link to its documentation
Your original function has a few issues:
It iterates the array using a for... in loop which has no guarantee on the iteration order. Also, don't use it to iterate through arrays - prefer a normal for... loop or a .forEach
You're iterating an array with an off-by-one error so you're skipping on the next item since you're both removing the element and progressing the array.
That is because the for-loop goes to the next item after the occurrence is deleted, thereby skipping the item directly after that one.
For example, lets assume item1 needs to be deleted in this array (note that <- is the index of the loop):
item1 (<-), item2, item3
after deleting:
item2 (<-), item3
and after index is updated (as the loop was finished)
item2, item3 (<-)
So you can see item2 is skipped and thus not checked!
Therefore you'd need to compensate for this by manually reducing the index by 1, as shown here:
function removeItem(item){
for(var i = 0; i < array.length; i++){
if(array[i]==item) {
array.splice(i,1);
i--; // Prevent skipping an item
}
}
}
Instead of using this for-loop, you can use more 'modern' methods to filter out unwanted items as shown in the other answer by Benjamin.
None of these answers are very optimal. The accepted answer with the filter will result in a new instance of an array. The answer with the second most votes, the for loop that takes a step back on every splice, is unnecessarily complex.
If you want to do the for loop loop approach, just count backward down to 0.
for (var i = array.length - 0; i >= 0; i--) {
if (array[i] === item) {
array.splice(i, 1);
}
}
However, I've used a surprisingly fast method with a while loop and indexOf:
var itemIndex = 0;
while ((itemIndex = valuesArray.indexOf(findItem, itemIndex)) > -1) {
valuesArray.splice(itemIndex, 1);
}
What makes this method not repetitive is that after the any removal, the next search will start at the index of the next element after the removed item. That's because you can pass a starting index into indexOf as the second parameter.
In a jsPerf test case comparing the two above methods and the accepted filter method, the indexOf routinely finished first on Firefox and Chrome, and was second on IE. The filter method was always slower by a wide margin.
Conclusion: Either reverse for loop are a while with indexOf are currently the best methods I can find to remove multiple instances of the same element from an array. Using filter creates a new array and is slower so I would avoid that.
You can use loadash or underscore js in this case
if arr is an array you can remove duplicates by:
var arr = [2,3,4,4,5,5];
arr = _.uniq(arr);
Try to run your code "manually" -
The "hello" are following each other. you remove the first, your array shrinks in one item, and now the index you have follow the next item.
removing "hello""
Start Loop. i=0, array=["hello","hello","world",1,"world"] i is pointing to "hello"
remove first item, i=0 array=["hello","world",1,"world"]
next loop, i=1, array=["hello","world",1,"world"]. second "hello" will not be removed.
Lets look at "world" =
i=2, is pointing to "world" (remove). on next loop the array is:
["hello","hello",1,"world"] and i=3. here went the second "world".
what do you wish to happen? do you want to remove all instances of the item? or only the first one? for first case, the remove should be in
while (array[i] == item) array.splice(i,1);
for second case - return as soon as you had removed item.
Create a set given an array, the original array is unmodified
Demo on Fiddle
var array=["hello","hello","world",1,"world"];
function removeDups(items) {
var i,
setObj = {},
setArray = [];
for (i = 0; i < items.length; i += 1) {
if (!setObj.hasOwnProperty(items[i])) {
setArray.push(items[i]);
setObj[items[i]] = true;
}
}
return setArray;
}
console.log(removeDups(array)); // ["hello", "world", 1]
I must say that my approach does not make use of splice feature and you need another array for this solution as well.
First of all, I guess your way of looping an array is not the right. You are using for in loops which are for objects, not arrays. You'd better use $.each in case you are using jQuery or Array.prototype.forEach if you are using vanila Javascript.
Second, why not creating a new empty array, looping through it and adding only the unique elements to the new array, like this:
FIRST APPROACH (jQuery):
var newArray = [];
$.each(array, function(i, element) {
if ($.inArray(element, newArray) === -1) {
newArray.push(region);
}
});
SECOND APPROACH (Vanila Javascript):
var newArray = [];
array.forEach(function(i, element) {
if (newArray.indexOf(element) === -1) {
newArray.push(region);
}
});
I needed a slight variation of this, the ability to remove 'n' occurrences of an item from an array, so I modified #Veger's answer as:
function removeArrayItemNTimes(arr,toRemove,times){
times = times || 10;
for(var i = 0; i < arr.length; i++){
if(arr[i]==toRemove) {
arr.splice(i,1);
i--; // Prevent skipping an item
times--;
if (times<=0) break;
}
}
return arr;
}
An alternate approach would be to sort the array and then playing around with the indexes of the values.
function(arr) {
var sortedArray = arr.sort();
//In case of numbers, you can use arr.sort(function(a,b) {return a - b;})
for (var i = 0; sortedArray.length; i++) {
if (sortedArray.indexOf(sortedArray[i]) === sortedArray.lastIndexOf(sortedArray[i]))
continue;
else
sortedArray.splice(sortedArray.indexOf(sortedArray[i]), (sortedArray.lastIndexOf(sortedArray[i]) - sortedArray.indexOf(sortedArray[i])));
}
}
You can use the following piece of code to remove multiple occurrences of value val in array arr.
while(arr.indexOf(val)!=-1){
arr.splice(arr.indexOf(val), 1);
}
I thinks this code much simpler to understand and no need to pass manually each element that what we want to remove
ES6 syntax makes our life so simpler, try it out
const removeOccurences = (array)=>{
const newArray= array.filter((e, i ,ar) => !(array.filter((e, i ,ar)=> i !== ar.indexOf(e)).includes(e)))
console.log(newArray) // output [1]
}
removeOccurences(["hello","hello","world",1,"world"])
I'm looking at an exercise and having trouble understand how the following works ( I'm trying to remove duplicates from an array)
var arr = ['a','b','c','a','b','d','e','f'];
var uniqueArray = arr.filter(function(item,pos){
return arr.indexOf(item) == pos;
});
My attempt to understand
Here item takes on all of our values in arr. Lets go through an iteration
First item = 'a' and pos = 0. Ok. now we want to only filter on the basis of if the index of 'a'is the same as 0
Here indexOf(a) == 0.
Great! this is true, lets put it in the new array.
Now lets move forward to where we see a again, namely at pos = 3
arr.indexOf(a) == 3
Wait... Doesent this meet our requirement as well? How does this even remove duplicates?
indexOf returns just one integer value, and it is the index of the first found item. So, when pos is 3 (and the item is a), indexOf will return 0 (because the first index of a is 0), 0==3 is false and the element will be removed.
Then, when the pos is 4 (and item is b), indexOf returns 2, the index of the first found b.
As for the objects, they can't have duplicate keys. Each new key will automatically overwrite the old one, so there won't be any duplicates.
Look:
var obj = {a:1, a:3, b:2,c:5,b:4};
console.log(obj)
nicael is right. indexOf(item) is just a function that goes through the array and looks for the first time item appears in the array, and returns the position in the array. In your example, if there is an a at 0 and a at index 3, then indexOf('a') will return position 0, while the value of pos is 3, so the filter returns false.
FOLLOW UP:
indexOf() has another parameter called the fromIndex, which lets you start the search from a position other than the beginning of the array. In this case, you can specify to skip over the first time 'a' occurs by doing arr.indexOf('a', 1) which starts the search at position 1, not 0. In this case the function would return true since the next 'a' is at position 3.
Can I use filter on an object?
No, because filter is a specific function of an Array object. You can get the keys of the object by doing a filter on Object.keys(myObject) since keys() returns an array.
Using your example:
var keyArray = Object.keys(myObject); //object can't have duplicate keys
keyArray.filter(function(item, index) {
return keyArray.indexOf(item) == index; //will never be false
});
Hashtable is the best way to eliminate the redundant values
Here is the code :
char arr[] = ['a','b','c','a','b','d','e','f'];
//it will contains all 26 places as zero (A - Z)
char hashArray[26]={0}
int i; //for iteration;
for(i=0;arr[i]!='\0';i++)
{
//it will subtracte the ascii value of the letter
//from 'a' so that we have the values from 0 to 26)
hashArray[arr[i]-'a']=arr[i];
}
for(i=0;i<26;i++)
{
if(hashArray[i]!=0) //to Ensure the positon has the character
{
printf("%c",hashArray[i]);
}
}
I have an array of objects and I am removing elements based on object value, without knowing which element it is.
So... those lovely people who flagged my question as duplicate and suggest I read How do I remove a particular element from an array in JavaScript? are not helping.
My question... again...
I have an array of objects
I want to search and remove specific elements from the array. I have a solution that is long winded (loop thru the array once, make a list of element id's, then slice one by one in another loop). I am hoping there is another method (enhance my skillset too).
myarray.filter(function(item)
{
if( item.flag==="Y" )
{
// how to delete element from myarray
// delete implies remove it from myarray
}
});
All help appreciated =)
You have at least two options:
Create a new array with filter
The first is to create a new array containing only the entries you want. You're already on the right track with filter:
myArray = myArray.filter(function(item) {
return item.flag !== "Y";
});
The new array will only have the entries that the callback returned a truthy value for. In this case, only ones whose flag is !== "Y". Entries whose flag is === "Y" will be left out of it.
Note that if you have other references to this same array in other variables, they will continue to point to the old array. Only myArray (in the above) gets a reference to the new array.
Modify the existing array with splice and a loop
The second is to use a while loop and splice:
var n = 0;
while (n < myArray.length) {
if (myArray[n].flag === "Y") {
// Remove it
myArray.splice(n, 1);
} else {
// Move to next
++n;
}
}
Note we don't move to next if we remove one, because we need to test the one after it (which is now at the previous index).
Or as Nina points out in a comment, a for loop going backward:
for (var n = myArray.length - 1; n >= 0; --n) {
if (myArray[n].flag === "Y") {
// Remove it
myArray.splice(n, 1);
}
}
In that case, since we're modifying the array (not creating a new one), the changes will be visible through any reference to that same array, not just myArray. (Since they all point to the same object, which we modified the state of.)
Remove object in array by its property-value:
Remove value: 30:
arr.splice(arr.map(el => el.value).indexOf(30), 1);
DEMO
Remove name: "John":
arr.splice(arr.map(el => el.name).indexOf("John"), 1);
I need to remove all elements in an array that do not contain "IN" in uppercase exactly like that.
How I thought of doing this was to traverse the array with a for loop and write all values that contain IN to another array.
Is there a way I can do it without writing to a new array and just removing those items that don't match from the current array?
Here is the code for how I was planning on doing it:
arrTwo = [];
for(var i = 0; i<arr.length; i++){
if(arr[i].indexOf('IN') > -1) arrTwo.push[arr[i]];
}
You can use ES5 filter method:
arr = arr.filter(function(s){
return ~s.indexOf("IN");
});
And using ES6 arrow functions, it can be simplified to:
arr = arr.filter(s=>~s.indexOf("IN"));
Here's a really good thread that has a couple of ways to accomplish this. If you do not delete the element of the array in the correct manner, you that element will be undefined rather than actually deleted. The .spilce() method is what you want to look into.
Deleting array elements in JavaScript - delete vs splice
I would do it using the splice() method:
var testArray = [ 'this one contains IN', 'this one does not' ];
function filterArray ( arr ) {
var i = arr.length;
//-- Loop through the array in reverse order since we are modifying the array.
while (i--) {
if (arr[i].indexOf('IN') < 0) {
//-- splice will remove the non-matching element
arr.splice(i, 1);
}
}
}
filterArray( testArray );
document.body.innerText = JSON.stringify(testArray);
JSFiddle: http://jsfiddle.net/5DW8L/1/
Basically, how do you return AND remove the first element of an array WITHOUT using the shift() OR splice() methods(or any other methods for that matter)?
thanks in advance!
What is the logic behind the 'shift' method?
It's fully described in the specification.
Basically, how do you return AND remove the first element of an array WITHOUT using the shift() OR splice() methods(or any other methods for that matter)?
I can't see any good reason for such a restriction, but you can use a loop to manually assign each entry the value of the one above it (starting at the end) until the index you want to change, and then set the length of the array to one less. Something vaguely like this (I'm sure this is not a complete implementation of what shift does):
Live example | Live source
var n;
for (n = theArray.length - 2; n >= removeAt; --n) {
theArray[n] = theArray[n+1];
}
--theArray.length;
Altering the length property of an array will remove any elements that no longer fall within the length.
You can also remove an element without altering the length of the array, using delete:
delete theArray[removeAt];
The array's length will be unchanged, but it will no longer have an entry (at all) at that location. It becomes sparse (if it wasn't already). This works because the delete statement removes properties from objects, and untyped JavaScript arrays are really just objects.
I think this is what you are looking for. It sets the first letter, then adds-on the rest of the string, replaces the first letter in the finalString variable with an empty string and then returns the first letter saved in the firstLetter variable.
function remove(str){
let firstLetter = '';
let finalString = '';
for(let i = 0; i < str.length; i++){
if(i === 0){
firstLetter = str[i];
}
finalString += str[i];
if(i === 0){
finalString = '';
}
}
return firstLetter;
}
remove('hello');