Remove oldest elements from a array - php

like
array(a, b, c, d, e);
I want to add new elements to it, but keep the maximum element count to 5. So if after the add the count exceeds 5, I want to remove elements from the start until the size of the array is 5 again.

For my suggestion I made use of array_sliceDocs:
Input:
$arr = range('a', 'c');
$new = 'f';
$highest = 4;
Code:
$arr = array_slice($arr, -$highest);
$arr[] = $new;
array_slice takes care to limit the array to the last 4 elements, then the new element is added.
If the array has less than 4 elements, this won't remove any elements, so only add the new one.
Demo

array_slice will help you
$array = array('a','b','c','d','e');
$array[] = 'f';
if(count($array) > 5)
$array = array_slice($array,count($array)-5);
var_dump($array);
reusable function
function add_array_max(&$array,$item,$max)
{
$array[] = $item;
if(count($array) > $max)
$array = array_slice($array,count($array)-$max);
}
add_array_max($array,'g',5);
add_array_max($array,'h',5);
add_array_max($array,'i',5);
add_array_max($array,'j',5);
var_dump($array);

Add elements in array and check following condition
if(count($arr) >= 5) {
array_shift($arr); //remove element from beginning
}

function add($array,$item) {
array_push($item);
while(count($array)>5) array_shift($array);
}

Try to use array_pad function.
(see http://www.php.net/manual/en/function.array-pad.php)
Or array_slice (see http://www.php.net/manual/en/function.array-slice.php)

Use a circular buffer, overwriting old elements and remembering the index of the "first" one.
add_element (k)
a [first] = k;
first = (first + 1) % 5
access_element (i)
return a [(first + i) % 5]

You can use this code:
$array = array('a', 'b', 'c', 'd', 'e');
$newElems = array ('f', 'g', 'h');
foreach($newElems as $elem)
{
array_shift($array);
array_push($elem);
}
It works as you can see here: http://codepad.org/DH2UUuTY

From http://php.net/manual/en/language.types.array.php:
The unset() function allows removing keys from an array. Be aware that
the array will not be reindexed. If a true "remove and shift" behavior
is desired, the array can be reindexed using the array_values()
function.
An example follows.

Try this:
if(count($array) >= 5)) { array_pop($array); }
array_push($array, 'whatever');

Related

Shifting the items in an array by a specified value

How would you go about circularly rotating the items in an array up or down by a specified value. For example
$value = 1; // circularly rotate by 1
$array = array(1,2,3,4,5);
// Should return
array(2,3,4,5,1);
The entire array is circularly rotated anti-clockwise by 1. 1 went to the end and 2 became the leading number in the array. I cannot find a reliable way to do this.
Use a for-loop with a specification on how many items you want moved, and array_shift() to shift the array. Then add the first element to a shifted array (which essentially moves the first item to the last element)
$shift = 2; // How many times you want to move it
$output = array(1, 2, 3, 4, 5);
for ($i = 0; $i < $shift; $i++) {
array_push($output , array_shift($output));
}
print_r($output); // 3, 4, 5, 1, 2
Live demo
References
http://php.net/manual/en/function.array-shift.php
http://php.net/manual/en/function.array-push.php
You can combine the array_push function that adds a value to the end of an array and the array_shift function that removes and returns the first element of an array.
<?php
$value = 1; // circularly rotate by 1
$array = array(1,2,3,4,5);
while ($value) {
array_push($array, array_shift($array));
$value--;
}
print_r($array);
?>

How to merge multiple arrays in PHP but mix values together - retaining their order [duplicate]

This question already has answers here:
Transpose and flatten two-dimensional indexed array where rows may not be of equal length
(4 answers)
Closed 5 months ago.
Is there a straightforward way in PHP to combine multiple arrays together but respect the relative order of the elements?
So for example if I had two arrays
$x = ('1','2','3','4');
and
$y = array('a','b','c','d','e');
and I wanted combine them into a single array
$z = ('1','a','2','b','3','c','4','d','e');
Is there a straightforward way of doing this? The ideal solution would also account for different lengths of arrays, behaving as my example does.
array_merge doesn't seem to achieve what I want as it just appends one array to the other.
My current solution loops through each array in order and pushes values to my $z array. This is not only inelegant, it also requires the input arrays to have the same number of values, which isn't ideal for my application.
Any insight would be appreciated
I think this should work -
$count = max(count($x), count($y));
$newArr = array();
for ($i = 0; $i < $count; $i++) {
// enter values to the new array based on key
foreach(array($x, $y) as $arr) {
if (isset($arr[$i])) {
$newArr[] = $arr[$i];
}
}
}
var_dump($newArr);
You could use this generic function, which can accept any number of arrays, and will output an array with the elements taken from the first "column" first, then from the second, etc:
function mix_merge(...$args) {
return call_user_func_array('array_merge',
array_map(function($i) use ($args) { return array_column($args, $i); },
range(0, max(array_map('count', $args))-1)));
}
// Sample data:
$x = array('1','2','3','4');
$y = array('a','b','c','d','e');
$z = array('A','B','C');
$res = mix_merge($x, $y, $z);
Result array will be:
['1', 'a', 'A', '2', 'b', 'B', '3', 'c', 'C', '4', 'd', 'e']
Iterate from 0 to the greater length of the two arrays.
At each step, if array $x contains item at index, push it to final array $z. Do the same for array $y.
You can also try this
$x = array('1','2','3','4');
$y = array('a','b','c','d','e');
foreach($y as $key=>$value){
if($x[$key]){
$z[] = $x[$key];
$z[] = $value;
}else {
$z[] = $value;
}
}

how to get array_diff to ignore duplicates in php? [duplicate]

I am using array_diff() to take values out of array1 which are found in array2. The issue is it removes all occurrences from array1, as the PHP documentations makes note of. I want it to only take out one at a time.
$array1 = array();
$array1[] = 'a';
$array1[] = 'b';
$array1[] = 'a';
$array2 = array();
$array2[] = 'a';
It should return an array with one 'a' and one 'b', instead of an array with just 'b';
Just for the fun of it, something that just came to mind. Will work as long as your arrays contain strings:
$a = array('a','b','a','c');
$b = array('a');
$counts = array_count_values($b);
$a = array_filter($a, function($o) use (&$counts) {
return empty($counts[$o]) || !$counts[$o]--;
});
It has the advantage that it only walks over each of your arrays just once.
See it in action.
How it works:
First the frequencies of each element in the second array are counted. This gives us an arrays where keys are the elements that should be removed from $a and values are the number of times that each element should be removed.
Then array_filter is used to examine the elements of $a one by one and remove those that should be removed. The filter function uses empty to return true if there is no key equal to the item being examined or if the remaining removal count for that item has reached zero; empty's behavior fits the bill perfectly.
If neither of the above holds then we want to return false and decrement the removal count by one. Using false || !$counts[$o]-- is a trick in order to be terse: it decrements the count and always evaluates to false because we know that the count was greater than zero to begin with (if it were not, || would short-circuit after evaluating empty).
Write some function that removes elements from first array one by one, something like:
function array_diff_once($array1, $array2) {
foreach($array2 as $a) {
$pos = array_search($a, $array1);
if($pos !== false) {
unset($array1[$pos]);
}
}
return $array1;
}
$a = array('a', 'b', 'a', 'c', 'a', 'b');
$b = array('a', 'b', 'c');
print_r( array_diff_once($a, $b) );

What's the most efficient way to array_pop() the last n elements in an array?

What's an efficient way to pop the last n elements in an array?
Here's one:
$arr = range(1,10);
$n = 2;
$popped_array = array();
for ($i=0; $i < $n; $i++) {
$popped_array[] = array_pop($arr);
}
print_r($popped_array); // returns array(10,9);
Is there a more efficient way?
Use array_splice():
If you're trying to remove the last n elements, use the following function:
function array_pop_n(array $arr, $n) {
return array_splice($arr, 0, -$n);
}
Demo
If you want to retrieve only the last n elements, then you can use the following function:
function array_pop_n(array $arr, $n) {
array_splice($arr,0,-$n);
return $arr;
}
Demo
It's important to note, looking at the other answers, that array_slice will leave the original array alone, so it will still contain the elements at the end, and array_splice will mutate the original array, removing the elements at the beginning (though in the example given, the function creates a copy, so the original array still would contain all elements). If you want something that literally mimics array_pop (and you don't require the order to be reversed, as it is in your OP), then do the following.
$arr = range(1, 10);
$n = 2;
$popped_array = array_slice($arr, -$n);
$arr = array_slice($arr, 0, -$n);
print_r($popped_array); // returns array(9,10);
print_r($arr); // returns array(1,2,3,4,5,6,7,8);
If you require $popped_array to be reversed, array_reverse it, or just pop it like your original example, it's efficient enough as is and much more direct.
Why not use array_slice. You can give a start and a length, so if you do 2 from the end you will get the last two items in the array:
$arr = range(1,10);
$n = 2;
$start = count($arr) - $n;
print_r(array_slice($arr, $start, $n));
Thanks for the array_slice comments. I don't know why that didn't immediately come to mind.
It looks (to me) like the easiest way is:
$arr = range(1,10);
$n = 2;
$popped_array = array_slice($arr,-$n);
print_r($popped_array); // returns array(10,9);

How to increase by 1 all keys in an array?

What is the simplest solution to increase by 1 all keys in an array?
BEFORE:
$arr[0] = 'a';
$arr[1] = 'b';
$arr[2] = 'c';
AFTER:
$arr[1] = 'a';
$arr[2] = 'b';
$arr[3] = 'c';
You can use
$start_zero = array_values($array); /* Re-Indexing Array To Start From Zero */
And if you want to start it from index 1 use
$start_one = array_combine(range(1, count($array)), array_values($array));
Well, there's one very simple way to do it:
$arr = array('a', 'b', 'c');
array_unshift($arr, null);
unset($arr[0]);
print_r($arr);
/*
Array
(
[1] => a
[2] => b
[3] => c
)
*/
Will work only for simple dense arrays, of course.
And this is most untrivial (yet both a one-liner AND working for both dense and sparse arrays) way:
$arr = array_flip(array_map(function($el){ return $el + 1; }, array_flip($arr)));
I'm not sure why you'd want to do this, but you should just be able to loop through:
$new_array = array();
foreach($arr as $key => $value){
$new_array[$key+1] = $value;
}
$arr = $new_array;
$count = count($arr);
for($i=$count; $i>0; $i--){
$arr[$i] = $arr[$i-1];
}
unset($arr[0]);
I know this question is quite old, but I ran into a similar issue recently and came up with a nice one-liner to solve it for any type of array using an arbitrary integer as the starting key:
$array = array_combine(array_keys(array_fill($starting_index, count($array), 0)), array_values($array));
$starting_index is whatever value you want for the initial integer key, e.g. 3.
This can even be used with arrays holding complex objects, unlike the solution using array_flip and does not limit you to starting the index at 0 or 1 like some of the other solutions.
I'm not sure if this qualifies as a one liner but it is a different way of doing it
$result = array_reduce(array_keys($arr),function($carry,$key) use($arr){
$carry[$key+1] = $arr[$key];
return $carry;
},[]);

Categories