Deleting Items from an Array Requires Multiple Passes to Remove Them All

Deleting items from an array requires multiple passes to remove them all

That's you modifying underlying collection while iterating over it.

Basically, if collection changes in some way during iteration (becomes empty, gets prepended with a new element, etc), iterator doesn't have a lot of ways to handle it.

Try reject instead.

list.reject! {|item| item.name =~ /cat|dog|rat/i }

How to remove multiple items from a list in just one statement?

In Python, creating a new object e.g. with a list comprehension is often better than modifying an existing one:

item_list = ['item', 5, 'foo', 3.14, True]
item_list = [e for e in item_list if e not in ('item', 5)]

... which is equivalent to:

item_list = ['item', 5, 'foo', 3.14, True]
new_list = []
for e in item_list:
if e not in ('item', 5):
new_list.append(e)
item_list = new_list

In case of a big list of filtered out values (here, ('item', 5) is a small set of elements), using a set is faster as the in operation is O(1) time complexity on average. It's also a good idea to build the iterable you're removing first, so that you're not creating it on every iteration of the list comprehension:

unwanted = {'item', 5}
item_list = [e for e in item_list if e not in unwanted]

A bloom filter is also a good solution if memory is not cheap.

Function to delete an element from an array not working

The problem is rather silly:

At the beginning of deleteElement(), you define i with int i = 0;, but you redefine another variable i as a local index in each for loop. The for loop introduces a new scope, so the int i definition in the first clause of the for loop defines a new i, that shadows the variable with the same name defined in an outer scope.

for (int i; i < length; i++) {

And you do not initialize this new i variable.

There are 2 consequences:

  • undefined behavior in the first loop as i is uninitialized. The comparison i < length might fail right away.
  • the test if (i == (length - 1)) { tests the outer i variable, not the one that for iterated on. Furthermore, the test should be if (i == length) {

There are other issues:

  • the nested for loop iterates once too many times: when j == length - 1, accessing array[j + 1] has undefined behavior.

  • you do not update length, so the last element of the array is duplicated. You must pass length by reference so it is updated in the caller's scope.

Here is a corrected version:

#include <iostream>

using namespace std;

void deleteElement(int array2[], int& length, int element);

int main() {

int array1[] = { 1, 4, 3, 5, 6 };

int length = sizeof(array1) / sizeof(array1[0]); //For length of array

deleteElement(array1, &length, 4);

cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i] << " ";
}
return 0;
}

void deleteElement(int array2[], int& length, int element) {

int i;

for (i = 0; i < length; i++) {
if (array2[i] == element)
break;
}

if (i == length) {
cout << "Element doesn't exist\n";
} else {
length -= 1;
for (; i < length; i++) {
array2[i] = array2[i + 1];
}
}

cout << "Testing OP in deleteElement\n";
for (i = 0; i < length; i++) {
cout << array2[i] << " ";
}
}

How to delete an item from state array?

To remove an element from an array, just do:

array.splice(index, 1);

In your case:

removePeople(e) {
var array = [...this.state.people]; // make a separate copy of the array
var index = array.indexOf(e.target.value)
if (index !== -1) {
array.splice(index, 1);
this.setState({people: array});
}
},

How can I remove a specific item from an array in JavaScript?

Find the index of the array element you want to remove using indexOf, and then remove that index with splice.

The splice() method changes the contents of an array by removing
existing elements and/or adding new elements.

const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) { // only splice array when item is found
array.splice(index, 1); // 2nd parameter means remove one item only
}

// array = [2, 9]
console.log(array);

Rails 3 - Remove items belonging to array B from array A

a = ["1","2","3","4","5","6"]
b = ["1","3"]
c = a - b

same as

c = a.reject{ |e| b.include? e }

Remove all elements contained in another array

Use the Array.filter() method:

myArray = myArray.filter( function( el ) {
return toRemove.indexOf( el ) < 0;
} );

Small improvement, as browser support for Array.includes() has increased:

myArray = myArray.filter( function( el ) {
return !toRemove.includes( el );
} );

Next adaptation using arrow functions:

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );

How to remove item from array by value?

This can be a global function or a method of a custom object, if you aren't allowed to add to native prototypes. It removes all of the items from the array that match any of the arguments.

Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
};

var ary = ['three', 'seven', 'eleven'];

ary.remove('seven');

/* returned value: (Array)
three,eleven
*/

To make it a global-

function removeA(arr) {
var what, a = arguments, L = a.length, ax;
while (L > 1 && arr.length) {
what = a[--L];
while ((ax= arr.indexOf(what)) !== -1) {
arr.splice(ax, 1);
}
}
return arr;
}
var ary = ['three', 'seven', 'eleven'];
removeA(ary, 'seven');

/* returned value: (Array)
three,eleven
*/

And to take care of IE8 and below-

if(!Array.prototype.indexOf) {
Array.prototype.indexOf = function(what, i) {
i = i || 0;
var L = this.length;
while (i < L) {
if(this[i] === what) return i;
++i;
}
return -1;
};
}

Remove an array element and shift the remaining ones

You just need to overwrite what you're deleting with the next value in the array, propagate that change, and then keep in mind where the new end is:

int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};

// delete 3 (index 2)
for (int i = 2; i < 8; ++i)
array[i] = array[i + 1]; // copy next element left

Now your array is {1, 2, 4, 5, 6, 7, 8, 9, 9}. You cannot delete the extra 9 since this is a statically-sized array, you just have to ignore it. This can be done with std::copy:

std::copy(array + 3, // copy everything starting here
array + 9, // and ending here, not including it,
array + 2) // to this destination

In C++11, use can use std::move (the algorithm overload, not the utility overload) instead.

More generally, use std::remove to remove elements matching a value:

// remove *all* 3's, return new ending (remaining elements unspecified)
auto arrayEnd = std::remove(std::begin(array), std::end(array), 3);

Even more generally, there is std::remove_if.

Note that the use of std::vector<int> may be more appropriate here, as its a "true" dynamically-allocated resizing array. (In the sense that asking for its size() reflects removed elements.)

remove objects from array by object property

I assume you used splice something like this?

for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];

if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
}
}

All you need to do to fix the bug is decrement i for the next time around, then (and looping backwards is also an option):

for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];

if (listToDelete.indexOf(obj.id) !== -1) {
arrayOfObjects.splice(i, 1);
i--;
}
}

To avoid linear-time deletions, you can write array elements you want to keep over the array:

var end = 0;

for (var i = 0; i < arrayOfObjects.length; i++) {
var obj = arrayOfObjects[i];

if (listToDelete.indexOf(obj.id) === -1) {
arrayOfObjects[end++] = obj;
}
}

arrayOfObjects.length = end;

and to avoid linear-time lookups in a modern runtime, you can use a hash set:

const setToDelete = new Set(listToDelete);
let end = 0;

for (let i = 0; i < arrayOfObjects.length; i++) {
const obj = arrayOfObjects[i];

if (setToDelete.has(obj.id)) {
arrayOfObjects[end++] = obj;
}
}

arrayOfObjects.length = end;

which can be wrapped up in a nice function:

const filterInPlace = (array, predicate) => {    let end = 0;
for (let i = 0; i < array.length; i++) { const obj = array[i];
if (predicate(obj)) { array[end++] = obj; } }
array.length = end;};
const toDelete = new Set(['abc', 'efg']);
const arrayOfObjects = [{id: 'abc', name: 'oh'}, {id: 'efg', name: 'em'}, {id: 'hij', name: 'ge'}];
filterInPlace(arrayOfObjects, obj => !toDelete.has(obj.id));console.log(arrayOfObjects);


Related Topics



Leave a reply



Submit