(I still need to clean this answer up a bit more later--which I will when I make the time.)
How to "remove an element" from an array in C. You might also call this "filtering an array" in C.
You can't resize statically-allocated arrays in C. Instead, you just keep track of a size variable and adjust it accordingly and only print what you need to.
Approach 1: [excellent] modify original array in-place
[best approach if you are okay modifying the original array]: modify the array in place by picking up only the elements you want to keep, and copying them into the same array from the left to the right
For n
elements in the array:
Time complexity: O(n)
Space complexity: O(1n) = O(n)
/// Get the number of elements in an array
#define ARRAY_LEN(array) (sizeof(array)/sizeof(array[0]))
int arr[] = {-3, -2, -1, 0, 1, 2, 3};
print_array(arr, ARRAY_LEN(arr));
size_t arr_len; // this will store the array's new length after modifications to it
// Remove values -1, 0, and +1 from the array
size_t i_write = 0;
for (size_t i_read = 0; i_read < ARRAY_LEN(arr); i_read++)
{
if (is_it_right(arr[i_read]))
{
arr[i_write] = arr[i_read];
i_write++;
}
}
arr_len = i_write;
print_array(arr, arr_len);
Sample output:
[-3, -2, -1, 0, 1, 2, 3]
[-3, -2, 2, 3]
Approach 2: [excellent] filter an array into another array
[best approach if you want to leave the original array as-is]
For n
elements in the array:
Time complexity: O(n)
Space complexity: O(2n) = O(n)
The easiest approach if you're trying to filter certain values from an array, however, is to just copy to a new array. So, here is a demo of that. In this demo, I begin with an array containing [-3, -2, -1, 0, 1, 2, 3]
, and I filter out all -1
, 0
, and +1
values with your little is_it_right()
algorithm, to end up with [-3, -2, 2, 3]
in the new array when I'm done.
To do that in-place in the same array would require a more-advanced algorithm that would almost certainly have the tradeoff of running slower, but, while not doubling the array space. The below approach will run very fast but I double the array space since I'm copying from one array into another rather than filtering the array in-place.
Anyway, study this carefully:
Run it online on OnlineGDB here.
Or download my full, runnable examples for both approaches below in my eRCaGuy_hello_world repo here: array_filter_and_remove_element.c
#include <stdbool.h>
#include <stdio.h>
/// Get the number of elements in an array
#define ARRAY_LEN(array) (sizeof(array)/sizeof(array[0]))
/// Return false for -1, 0, or +1, and return true otherwise.
bool is_it_right(int i)
{
if (i/2 == 0)
{
return false;
}
return true;
}
void print_array(int arr[], size_t len)
{
printf("[");
for (size_t i = 0; i < len; i++)
{
printf("%i", arr[i]);
if (i < len - 1)
{
printf(", ");
}
}
printf("]\n");
}
int main()
{
int arr[] = {-3, -2, -1, 0, 1, 2, 3};
int arr_filtered[ARRAY_LEN(arr)];
size_t arr_filtered_len;
// Remove values -1, 0, and +1 from the array
int j = 0;
for (size_t i = 0; i < ARRAY_LEN(arr); i++)
{
if (is_it_right(arr[i]))
{
arr_filtered[j] = arr[i];
j++;
}
}
arr_filtered_len = j;
print_array(arr, ARRAY_LEN(arr));
print_array(arr_filtered, arr_filtered_len);
return 0;
}
Output:
[-3, -2, -1, 0, 1, 2, 3]
[-3, -2, 2, 3]
Approach 3: [not good] "erase" an element by left-shifting
[way more complicated and processor-intensive and copy-intensive] filter an array in-place by left-shifting all the elements which lie to the right of an element you remove, each time you remove one element
For n
elements in the array:
Time complexity: best-case (nothing to filter out): O(n); worst-case (all elements must be filtered out 1-at-a-time): O(n^2)
Space complexity: O(1n) = O(n)
This approach is way more complicated, more processor-intensive, and more copy-intensive. I recommend the approach above instead.
printf("\n====================================\n"
"APPROACH 2: FILTER AN ARRAY IN-PLACE\n"
"====================================\n");
// Remove values -1, 0, and +1 from the array **in place**
size_t arr_len = ARRAY_LEN(arr);
printf("Starting array:\n");
print_array(arr, arr_len);
size_t i = 0;
while (i < arr_len)
{
if (is_it_right(arr[i]) == false)
{
// We don't want to keep this value at `arr[i]`, so overwrite it
// by shifting all values from `i + 1` to the end of the array to
// the left by 1 place.
printf("Removing value `%i` from the array\n", arr[i]);
size_t i_write = i;
for (size_t i_read = i_write + 1; i_read < arr_len; i_read++)
{
arr[i_write] = arr[i_read];
i_write++;
print_array(arr, arr_len);
}
arr_len--;
printf("One element has just been removed. Here is the new array:\n");
print_array(arr, arr_len);
}
else // is_it_right(arr[i]) == true
{
// only increment `i` if we did NOT just left-shift a bunch of
// elements by one index place
i++;
}
}
printf("Here is the final, filtered-in-place array:\n");
print_array(arr, arr_len);
Sample output:
====================================
APPROACH 2: FILTER AN ARRAY IN-PLACE
====================================
Starting array:
[-3, -2, -1, 0, 1, 2, 3]
Removing value `-1` from the array
[-3, -2, 0, 0, 1, 2, 3]
[-3, -2, 0, 1, 1, 2, 3]
[-3, -2, 0, 1, 2, 2, 3]
[-3, -2, 0, 1, 2, 3, 3]
One element has just been removed. Here is the new array:
[-3, -2, 0, 1, 2, 3]
Removing value `0` from the array
[-3, -2, 1, 1, 2, 3]
[-3, -2, 1, 2, 2, 3]
[-3, -2, 1, 2, 3, 3]
One element has just been removed. Here is the new array:
[-3, -2, 1, 2, 3]
Removing value `1` from the array
[-3, -2, 2, 2, 3]
[-3, -2, 2, 3, 3]
One element has just been removed. Here is the new array:
[-3, -2, 2, 3]
Here is the final, filtered-in-place array:
[-3, -2, 2, 3]
Again, the full, runnable examples for both approaches above are in my eRCaGuy_hello_world repo here: array_filter_and_remove_element.c
See also
- [a similar answer of mine in C++, but for strings--ex:
std::string
type] Removing all the vowels in a string in c++