How to get numeric key of new pushed item in PHP? - php

$arr[] = $new_item;
Is it possible to get the newly pushed item programmatically?
Note that it's not necessary count($arr)-1:
$arr[1]=2;
$arr[] = $new_item;
In the above case,it's 2

end() do the job , to return the value ,
if its help to you ,
you can use key() after to petch the key.
after i wrote the answer , i see function in this link :
http://www.php.net/manual/en/function.end.php
function endKey($array){
end($array);
return key($array);
}

max(array_keys($array)) should do the trick

The safest way of doing it is:
$newKey = array_push($array, $newItem) - 1;

You can try:
max(array_keys($array,$new_item))
array_keys($array,$new_item) will return all the keys associated with value $new_item, as an array.
Of all these keys we are interested in the one that got added last and will have the max value.

You could use a variable to keep track of the number of items in an array:
$i = 0;
$foo = array();
$foo[++$i] = "hello";
$foo[++$i] = "world";
echo "Elements in array: $i" . PHP_EOL;
echo var_dump($foo);

if it's newly created, you should probably keep a reference to the element. :)
You could use array_reverse, like this:
$arr[] = $new_item;
...
$temp = array_reverse($arr);
$new_item = $temp[0];
Or you could do this:
$arr[] = $new_item;
...
$new_item = array_pop($arr);
$arr[] = $new_item;
If you are using the array as a stack, which it seems like you are, you should avoid mixing in associative keys. This includes setting $arr[$n] where $n > count($arr). Stick to using array_* functions for manipulation, and if you must use indexes only do so if 0 < $n < count($arr). That way, indexes should stay ordered and sequential, and then you can rely on $arr[count($arr)-1] to be correct (if it's not, you have a logic error).

Related

Right rotation on array in php

I have an array for example
$a = [1,2,3,4,5];
From this $a, how to take last one and set it first like [5,1,2,3,4]
And how do I take last two arrays to make it like [4,5,1,2,3]
You can combine using array_pop(), which pops the last element of the array out, and array_unshift() to push it to the front of the array. You can create a simple function for this,
function array_pop_unshift($array) {
array_unshift($array, array_pop($array));
return $array;
}
Then use it as
$a = [1,2,3,4,5];
$new = array_pop_unshift($a);
print_r($new); // [5,1,2,3,4]
To continue shifting it, just call the function again until you're done, for instance through a for loop,
$a = [1,2,3,4,5];
for ($i = 0; $i < 2; $i++) {
$new = array_pop_unshift($a);
}
print_r($new); // [4,5,1,2,3]
Live demo at https://3v4l.org/CoJZZ
If you want to avoid the cost of several array_unshift and array_pop, you can build a generator that plays with the array internal pointer.
If you really need a result array, use iterator_to_array() to create it:
$a = range(1,5);
function rotate(&$array, $step = 1) {
$length = count($array);
end($array);
while ($step--)
prev($array);
while ($length--) {
next($array);
if (key($array) === null)
reset($array);
yield current($array);
}
}
print_r(iterator_to_array(rotate($a, 2))); // [4,5,1,2,3]
demo
Note that the rotate() generator uses a reference to avoid the array copy but doesn't modify the orginal array: it only moves the array pointer n times (where n is the array length) from the choosen position. When the array pointer is out of the array (key() returns null) the array pointer is reseted. In other words it stays efficient even with a large array and many rotations (what I have called "step" in the code).
You are actually doing right rotation, not left. Anyway, here are functions for doing both of them. They are probably not the most efficient but they are short in code and pretty self-explanatory:
<?php
function rotateLeft($array, $times) {
for($i=0; $i<$times; $i++){
$array[] = array_shift($array);
}
return $array;
}
function rotateRight($array, $times) {
for($i=0; $i<$times; $i++){
array_unshift($array, array_pop($array));
}
return $array;
}
$a = [1,2,3,4,5];
$a = rotateRight($a, 1);
print_r($a);
?>
to take last one and set it first This is known as right rotation.
And
$k is the number of units the shifting should be. $a is the array.
for($x=0; $x < $k; $x++){
//remove last element
$last = array_pop($a);
//push last element to the beginning
array_unshift($a, $last);
}
array_pop() pops and returns the value of the last element of array, shortening the array by one element.
https://www.php.net/manual/en/function.array-pop.php
array_unshift() prepends passed elements to the front of the array
https://www.php.net/manual/en/function.array-unshift.php
You could create a function that takes two arguments $k(number of rotations), $a (the array) and returns the array after performing right rotation $k times.
function rotateRight($a, $k){
for($x=0; $x < $k; $x++){
//remove last element
$last = array_pop($a);
//push last element to the beginning
array_unshift($a, $last);
}
return $a;
}
And then call it accordingly.
Example:
$a = [1,2,3,4,5];
$a_one_shift = rotateRight($a, 1);
// [5,1,2,3,4];
$a_two_shift = rotateRight($a_one_shift, 1);
// [4,5,1,2,3];
Or you could pass 2 to directly get the array after two right rotations.
$a_new = rotateRight($a, 2);
// [4,5,1,2,3];
Rather than making iterated calls of array_pop() and array_unshift(), use an efficient, elegant approach that makes fewer function calls and has the lowest possible time complexity. Using early returns prevents making needless function calls for the same result.
Code: (Demo)
function popUnshift(array $indexedArray, int $popShiftsCount): array
{
$count = count($indexedArray);
if ($count < 2) {
return $indexedArray; // array cannot be rotated
}
$remainder = $popShiftsCount % $count;
if (!$remainder) {
return $indexedArray; // sought rotation is the original order
}
return array_merge(
array_splice($indexedArray, -$remainder),
$indexedArray
);
}
Disclosure: This answer was built on the CodeReview page (Codility cyclic rotation solution in PHP) where I offered this snippet in my review.
//$A input array, $K rotation times
function solution($A, $K) {
$new = array();
for($j=1;$j<=$K;$j++)
{
if(count($new)>0)
$A = $new;
for($i=0;$i<count($A);$i++)
{
if($i==0)
$new[$i] = $A[count($A)-1];
else
$new[$i] = $A[$i-1];
}
}
return $new;}

Iterate on PHP variable (list/array) then output the index based on its value

Using the following example in PHP:
$priv['PAGE_A'] = 11;
$priv['PAGE_B'] = 22;
$priv['PAGE_C'] = 33;
$priv['PAGE_D'] = 44;
1) I would like to iterate on the 4 values in $priv. Would 'foreach' be the correct way to do it?
2) If the value is higher than a given number, I would like to echo the index of this value. Not sure how to do it. The comparaison must be INT (not string).
Ex. using "30" it would output:
PAGE_C
PAGE_D
Is it possible? Or maybe I am not using the correct container for what I'm trying to do ?
PS. How would you call the type of "$priv" in this example ? An array ? An indexed variable ? A dictionary ? A list ?
Thank you.
basically:
<?php
function foo($var){
$priv['PAGE_A'] = 11;
$priv['PAGE_B'] = 22;
$priv['PAGE_C'] = 33;
$priv['PAGE_D'] = 44;
$out='';
foreach ($priv as $k=>$v){
if ($v >$var){
$out .= $k.'<br>';
}
}
return $out;
}
echo foo('30');
demo: http://codepad.viper-7.com/GNX7Gf
Just create an array with the letters to iterate over.
$letters = array('A','B','C','D');
for($i=0;$i<count($letters);$i++) {
if($priv['PAGE_' . $letters[$i]] > /*value*/) {
echo $priv['PAGE_' . $letters[$i]];
}
}
$priv is an array.
Also, it's not too clear to me what you are exactly trying to do. Are you trying to echo the value of the array element if it's greater than a constant value?
We could do it using PHP builtin array functions. Its good to use builtin functions if possible in case of performance.
array_walk will do the trick for you. In this case $priv is an associative PHP array. Following is the one line script that will do what you want to achieve:
$input = 30;
$priv['PAGE_A'] = 11;
$priv['PAGE_B'] = 22;
$priv['PAGE_C'] = 33;
$priv['PAGE_D'] = 44;
array_walk($priv, function($value, $key, $input){ if($value > $input) echo $key . '<br>';}, $input);

Print array value and variable in order

I am sure there is a simpler solution to this that I am over looking
Here is some code that basically describes what I am doing:
$array = array('1.4','2.7','4.1','5.9');
$score = '4.4';
foreach($array as $value) {
if($score>$value){
$x = $value;
}
}
foreach($array as $value) {
if($x==$value){
echo $value."<br>";
echo $score."<-- <br>";
} else {
echo $value."<br>";
}
}
Will display as:
1.4
2.7
4.1
4.4<--
5.9
What I am trying to do is print the array values with the score value in order.
Why don't you change the array to actual numerical values and then sort it?
$array = array(1.4, 2.7, 4.1, 5.9);
$score = 4.4;
$array[] = $score;
sort($array);
Or if you need to work with strings:
$array = array('1.4', '2.7', '4.1', '5.9');
$score = '4.4';
$array[] = $score;
sort($array, SORT_NUMERIC);
For sorting, what might be the easiest is to use the sort() method (docs).
You're overwriting $x each time through your first loop. ... the way it's written, when you're done with the first loop, $x has the last value that's less than $score. (Are you identifying a cut-off line?)
After you've sorted with the sort() method, your second loop should work as you intend. There are tighter ways to do the printing (for example, you can implode()), but what you've got should work.

php explode and force array keys to start from 1 and not 0

I have a string that will be exploded to get an array, and as we know, the output array key will start from 0 as the key to the first element, 1 for the 2nd and so on.
Now how to force that array to start from 1 and not 0?
It's very simple for a typed array as we can write it like this:
array('1'=>'value', 'another value', 'and another one');
BUT for an array that is created on the fly using explode, how to do it?
Thanks.
$exploded = explode('.', 'a.string.to.explode');
$exploded = array_combine(range(1, count($exploded)), $exploded);
var_dump($exploded);
Done!
Just use a separator to create a dummy element in the head of the array and get rid of it afterwards. It should be the most efficient way to do the job:
function explode_from_1($separator, $string) {
$x = explode($separator, $separator.$string);
unset($x[0]);
return $x;
}
a more generic approach:
function explode_from_x($separator, $string, $offset=1) {
$x = explode($separator, str_repeat($separator, $offset).$string);
return array_slice($x,$offset,null,true);
}
$somearray = explode(",",$somestring);
foreach($somearray as $key=>$value)
{
$otherarray[$key+1] = $value;
}
well its dirty but isn't that what php is for...
Nate almost had it, but needed a temporary variable:
$someArray = explode(",",$myString);
$tempArray = array();
foreach($someArray as $key=>$value) {
$tempArray[$key+1] = $value;
}
$someArray = $tempArray;
codepad example
$array = array('a', 'b', 'c', 'd');
$flip = array_flip($array);
foreach($flip as &$element) {
$element++;
}
$normal = array_flip($flip);
print_r($normal);
Try this, a rather funky solution :P
EDIT: Use this instead.
$array = array('a', 'b', 'b', 'd');
$new_array = array();
$keys = array_keys($array);
for($i=0; $i<count($array); $i++) {
$new_array[$i+1] = $array[$i];
}
print_r($new_array);
I agree with #ghoti that this task is probably an XY Problem. I can't imagine a valid/professional reason to start keys from 1 -- I've never needed this functionality in over 10 years of development. I'll offer a compact looping approach, but I'll probably never need it myself.
After instatiating a counter which is one less than the desired first key, you can use a body-less foreach() as a one-liner.
Code: (Demo)
$i = 0;
$result = [];
foreach (explode('.', 'a.string.to.explode') as $result[++$i]);
var_export($result);

PHP unreference

Lets say i have this code:
$val = 1;
$arr = Array();
$arr['val'] =& $val;
$val = 2;
echo $arr['val'];
This will print out 2, because $val was passed to $arr by reference.
My question is : if i passed a value to an array by reference, is there a way to remove that reference later on, making it a simple copied value ?
To make it clearer, i would like something like this:
$val = 1;
$arr = Array();
$arr['val'] =& $val;
$arr['val'] = clone $arr['val'];
// Or better yet:
$arr = clone $arr;
$val = 2;
echo $arr['val'];
And this should print out 1 (because the array was cloned, before the referenced variable changed).
Howerver, clone does not work with arrays, it only works with objects.
Any ideas? I really have no clue how to do this. I tried writing a recursive copy function, but that didn't work.
You could unset the index and then reassign by-value instead of by reference.
unset($arr['val']);
$arr['val'] = $val;

Categories