php - array_fill negative indices - php

When using php array_fill and negative indices, why does php only fill the first negative indice and then jump to 0.
For example:
array_fill(-4,4,10) should fill -4, -3, -2, -1 and 0 but it does -4, 0, 1, 2, 3
The manual does state this behaviour but not why.
Can anyone say why this is?

Looking at the source for PHP, I can see exactly why they did this!
What they do is create the first entry in the array. In PHP, it looks like:
$a = array(-4 => 10);
Then, they add each new entry like this:
$count--;
while ($count--) {
$a[] = 10;
}
If you do this exact same thing yourself, you'll see the exact same behavior. A super short PHP script demonstrates this:
<?php
$a = array(-4 => "Apple");
$a[] = "Banana";
print_r($a);
?>
The result: Array ( [-4] => Apple [0] => Banana )
NOTE
Yes, I did put in PHP instead of the C source they used, since a PHP programmer can understand that a lot better than the raw source. It's approximately the same effect, however, since they ARE using the PHP functions to generate the results...

Maybe because it's stated in the doc: http://www.php.net/manual/en/function.array-fill.php
If start_index is negative, the first index of the returned array will be start_index and the following indices will start from zero (see example).

Related

Zero in increment array started at 1

This is my code, it's for have an array :
$zi = '1';
for ($zi = 1; $zi <= $v['Store']['stock']; $zi++) {
$options_array[$zi]= $zi;
}
var_dump($options_array);
Array
(
[0] => 0
[1] => 1
[2] => 2
)
why i have the zero in my result ?
i put $zi at 1, so why ?
As my comment turned out to be correct: The issue is that you already have a property 0 in the $options_array before you even get to the presented code block. You can start with a fresh array using $options_array = [] or $options_array = array() (for older php versions). You can also just remove property 0 with unset($options_array[0]).
In php there are two kinds of arrays, numerically indexed arrays, and associative arrays. Your output seems a little suspect but I can tell you that if all the keys of a PHP array are numeric then the array will be zero based.
I see how you have $zi = '1' above, which is along the lines of what you would have to do to create a one based array, but it would be associative, and you won't be able to simply use the ++ operator. I believe even if you use a string that is a number PHP will still convert to a numerically indexed array. I recommend against trying to implement a one based array, it's insanity.
Hope this page helps http://us2.php.net/manual/en/language.types.array.php
You start setting $options_array at index 1, so index 0 is whatever the default value of the underlying type is. In this case, it's an integer, so the default is 0.

Sorting PHP Randomised numbers by size

So I've got this:
$h = $user_goals;
while($h > 0) {
randomScorer();
$minute = rand(0,90);
echo "(".$minute.")<br>";
$h--;
Basically, what it does is, $user_goals, has a load of factors drawn into it and creates a number, between 0-5, and this information is used to generate the times of the goals, using the above PHP function.
It's working, it's brilliant, etc. However, the numbers are appearing in random order in which they are generated and so I was wondering:
Is there any way to sort these numbers?
Would I put them into an array during this iteration methodology, and then sort the array by the number's value?
Any help is greatly appreciated!
That is why PHP provides us Sort functions. Have a look here.
<?php
$fruits = array("lemon", "orange", "banana", "apple");
sort($fruits);
?>
Since your array is NUMERIC, you need to use the FLAG along with the sort function.
sort($goals, SORT_NUMERIC);
print_r($goals);
Same idea, using sort() but also uses range and array_walkto set up your array a little closer to how you already do it:
$goal_array = range(1, $user_goals); // Warning, assumes $user_goals is number
array_walk($goal_array, function(&$goal) {
randomScorer();
$goal = rand(0,90);
});
sort($goal_array, SORT_NUMERIC);

php difference between pack() and unpack()

in php 4.4.4 having:
$hbc=pack("LL",82603088,82602992);
list($v1,$v2)=unpack("L2",$hbc);
echo("v1=".$v1." v2=".$v2);
result is:
v1= v2=82603088
I already have some hours wrapping my head aroud this...
thanks
The error is not withing the pack or unpack, but inside the list().
Turn on notices! Your code will complain like this:
Notice: Undefined offset: 0 in ...
That should make you wonder. If you dump the array that is returned by unpack, it is correct:
array(2) {
[1] =>
int(82603088)
[2] =>
int(82602992)
}
And then there is this tiny little note on the docs page of list():
list() only works on numerical arrays and assumes the numerical indices start at 0.
Your array does not start at index 0, and the notice likes to tell you that.
The quick fix is:
list(,$v1,$v2)=unpack("L2",$hbc); // add a comma to skip index 0
A better approach might be to use unpack to create named array indices:
$unpacked = unpack("L2v/",$hbc);
Result:
array(2) {
'v1' =>
int(82603088)
'v2' =>
int(82602992)
}
From the php.net comments.
$int_list = array_merge(unpack("s*", $some_binary_data));
This will essentially reset your index keys starting at 0.

How do I move an array element with a known key to the end of an array in PHP?

Having a brain freeze over a fairly trivial problem. If I start with an array like this:
$my_array = array(
'monkey' => array(...),
'giraffe' => array(...),
'lion' => array(...)
);
...and new elements might get added with different keys but always an array value. Now I can be sure the first element is always going to have the key 'monkey' but I can't be sure of any of the other keys.
When I've finished filling the array I want to move the known element 'monkey' to the end of the array without disturbing the order of the other elements. What is the most efficient way to do this?
Every way I can think of seems a bit clunky and I feel like I'm missing something obvious.
The only way I can think to do this is to remove it then add it:
$v = $my_array['monkey'];
unset($my_array['monkey']);
$my_array['monkey'] = $v;
array_shift is probably less efficient than unsetting the index, but it works:
$my_array = array('monkey' => 1, 'giraffe' => 2, 'lion' => 3);
$my_array['monkey'] = array_shift($my_array);
print_r($my_array);
Another alternative is with a callback and uksort:
uksort($my_array, create_function('$x,$y','return ($y === "monkey") ? -1 : 1;'));
You will want to use a proper lambda if you are using PHP5.3+ or just define the function as a global function regularly.
I really like #Gordon's answer for its elegance as a one liner, but it only works if the targeted key exists in the first element of the array. Here's another one-liner that will work for a key in any position:
$arr = ['monkey' => 1, 'giraffe' => 2, 'lion' => 3];
$arr += array_splice($arr, array_search('giraffe', array_keys($arr)), 1);
Demo
Beware, this fails with numeric keys because of the way that the array union operator (+=) works with numeric keys (Demo).
Also, this snippet assumes that the targeted key is guaranteed to exist in the array. If the targeted key does not exist, then the result will incorrectly move the first element to the end because array_search() will return false which will be coalesced to 0 by array_splice() (Demo).
You can implement some basic calculus and get a universal function for moving array element from one position to the other.
For PHP it looks like this:
function magicFunction ($targetArray, $indexFrom, $indexTo) {
$targetElement = $targetArray[$indexFrom];
$magicIncrement = ($indexTo - $indexFrom) / abs ($indexTo - $indexFrom);
for ($Element = $indexFrom; $Element != $indexTo; $Element += $magicIncrement){
$targetArray[$Element] = $targetArray[$Element + $magicIncrement];
}
$targetArray[$indexTo] = $targetElement;
}
Check out "moving array elements" at "gloommatter" for detailed explanation.
http://www.gloommatter.com/DDesign/programming/moving-any-array-elements-universal-function.html

Which is proper form?

PHP.
$a['0']=1;
$a[0]=2;
Which is proper form?
In the first example you use a string to index the array which will be a hashtable "under the hood" which is slower. To access the value a "number" is computed from the string to locate the value you stored. This calculation takes time.
The second example is an array based on numbers which is faster. Arrays that use numbers will index the array according to that number. 0 is index 0; 1 is index 1. That is a very efficient way of accessing an array. No complex calculations are needed. The index is just an offset from the start of the array to access the value.
If you only use numbers, then you should use numbers, not strings. It's not a question of form, it's a question of how PHP will optimize your code. Numbers are faster.
However the speed differences are negligible when dealing with small sizes (arrays storing less than <10,000 elements; Thanks Paolo ;)
In the first you would have an array item:
Key: 0
Index: 0
In the second example, you have only an index set.
Index: 0
$arr = array();
$arr['Hello'] = 'World';
$arr['YoYo'] = 'Whazzap';
$arr[2] = 'No key'; // Index 2
The "funny" thing is, you will get exactly the same result.
PHP (for whatever reason) tests whether a string used as array index contains only digits. If it does the string is converted to int or double.
<?php
$x=array(); $x['0'] = 'foo';
var_dump($x);
$x=array(); $x[0] = 'foo';
var_dump($x);
For both arrays you get [0] => foo, not ["0"] => foo.
Or another test:<?php
$x = array();
$x[0] = 'a';
$x['1'] = 'b';
$x['01'] = 'c';
$x['foo'] = 'd';
foreach( $x as $k=>$v ) {
echo $k, ' ', gettype($k), "\n";
}0 integer
1 integer
01 string
foo string
If you still don't believe it take a look at #define HANDLE_NUMERIC(key, length, func) in zend_hash.h and when and where it is used.
You think that's weird? Pick a number and get in line...
If you plan to increment your keys use the second option. The first one is an associative array which contains the string "0" as the key.
They are both "proper" but have the different side effects as noted by others.
One other thing I'd point out, if you are just pushing items on to an array, you might prefer this syntax:
$a = array();
$a[] = 1;
$a[] = 2;
// now $a[0] is 1 and $a[1] is 2.
they are both good, they will both work.
the difference is that on the first, you set the value 1 to a key called '0'
on the second example, you set the value 2 on the first element in the array.
do not mix them up accidentally ;)

Categories