PHP shuffle not working like expected on my nested array - php

I have a nested array of arrays, and I want to shuffle the inner arrays. My code looks like this (simplified):
$a = array(array('banana', 'peach'), array('ding', 'dong'), array('oh snow'));
foreach ($a as &$arr) {
shuffle($arr);
}
var_dump($a);
The var_dump outputs this:
array(3) { [0]=> array(2) { [0]=> string(5) "peach" [1]=> string(6) "banana" } [1]=> array(2) { [0]=> string(4) "ding" [1]=> string(4) "dong" } [2]=> &array(1) { [0]=> string(7) "oh snow" } }
As you can see in the output, the first two subarrays work, but the third subarray is linked by reference in the output...
In my full app, this last array-link causes problems, but rather than working around the issue, I want to fix this shuffle thing...
Cheers!

This has to do with how PHP stores references to array elements. It cannot reference an element of an array, only values. Therefore it has to store the value array('oh snow') in a "slot" of the symbol table, then make $arr and $a[2] a reference to that value.
To fix this, unset($arr) after the loop. That way only a single variable is referencing the value, which will then be made a regular array index again. Unsetting references after a foreach is good practice anyway, since there are many such gotchas.

Related

php sort array without custom function

Here is an extract of my test code and data:-
//Update Array
$civs[1][1]="1";
$civs[1][2]="Inca";
$civs[2][1]="2";
$civs[2][2]="India";
//Sort Array
array_multisort($civs[0][2], SORT_DESC, SORT_STRING,
$civs[0][1], SORT_NUMERIC, SORT_DESC);
Output:-
Warning: array_multisort(): Argument #1 is expected to be an array or
a sort flag in ~/test.php on line 3
array(3) { [1]=> array(2) { [1]=> string(1) "1" [2]=> string(4) "Inca" } [2]=> array(2) { [1]=> string(1) "2" [2]=> string(5) "India" } [0]=> array(2) { [2]=> NULL [1]=> NULL } }
Problem statement
Depending on what the User selects I need to sort the array in PHP either on the 1st (numeric) or 2nd (alphanumeric) element of the 2nd part of the array but can't see how to do that, the various PHP sorts don't seem to allow you to tell it what is to be sorted on, have tried the above code . The PHP Manual for uksort says "If the array you wish to sort needs to be sorted by some non-trivial criteria," well numeric is about as trivial as it gets!
I've been looking at this for a couple of hours now and am sure I must be missing something as all I can see is that I have to write a custom function but surely PHP knows how to do simple sorts based on numeric or text values?
Main question I found was this:- How can I sort arrays and data in PHP? and I also spent a fair bit of time browsing through http://php.net/manual/en/array.sorting.php.
Apologies if I have missed something obvious.

Dealing with php array whose content may or may not have another array

I am dealing with arrays whose structure is different depending on the number or items in the array.
For example, the following is the array with one item in it.
// Case #1
["Assignment"]=>
object(stdClass)#29 (9) {
["Id"]=> string(10) "1234567890"
..
}
However if there are more than 1 item in the array,
// Case #2
["Assignment"]=>
array(2) {
[0]=>
object(stdClass)#28 (9) {
["Id"]=> string(10) "1234567890"
..
}
[1]=>
object(stdClass)#28 (9) {
["Id"]=> string(10) "1234567890"
..
}
}
Notice that the contents are in another array for this. No matter of how many items there are, I want to access the Id. $array->Id will work for one case but won't work for the other with the error saying, Trying to get property of non-object.
I could come up with an inefficient way by counting the # of contents in the array like this:
// say the arrays above are declared as $assignment
if($numOfAssignment > 1) {
foreach($assignment as $key) {
echo $key->Id;
}
}
else {
echo $assignment->Id;
}
But if the code was a bit lengthy, I feel it is too repetitive and inefficient.
Is there a way to do this in one effective phrase no matter of the number of the contents inside the array? Let me know if anything is unclear. Thanks!
What you can do is change the non-array into an array with a single element, then you can process it consistently.
if (!is_array($assignment)) {
$assignment = array($assignment);
}
foreach ($assignment as $key) {
echo $key=>Id;
}

PHP Array_intersect on multidimensional array with unknown number of keys

I'm trying to make advanced search filters in an application that holds resources (people). I've got all the results in 1 multidimensional array. A user of the application can search for the persons Job title, skills, work field and country.
I've already made the part where I look up the people that meet the criteria given by the user. These results are stored in a multidimensional array. If the user is looking for someone with a specific resource with a job title and a specific skill the return value is this:
$realfilters = array(2) {
["resourcesWithJobtitle"]=> array(6) {
[0]=> string(1) "1"
[1]=> string(2) "48"
[2]=> string(2) "88"
}
["resourcesWithSkill"]=> array(9) {
[0]=> string(1) "4"
[1]=> string(1) "8"
[2]=> string(1) "48"
[3]=> string(2) "50"
}
When the user also looks for a work field this is added to the result:
["resourcesWithWorkfield"]=> array(3) {
[0]=> string(2) "48"
[1]=> string(2) "96"
[2]=> string(2) "97"
}
I need to know which resources meet all dimensions of the array so I can display them. (So in this example I need an array with just 1 value: 48). I think I need to use array_intersect but can't seem to get it right.
One of the possible solutions: you may first extract() the $realfilters array values to variables, and then apply the array_intersect() to them. But this solution is applicable only if there are not many possible filters.
Another one and probably the best solution would be to intersect in a loop, something like:
$res_arr = array_shift($realfilters);
foreach($realfilters as $filter){
$res_arr = array_intersect($res_arr, $filter);
}
$intersection = call_user_func_array('array_intersect', $array);
That will give you the elements present in all the sub arrays of $array.
edit-
This above is like a shortcut for writing:
$intersection = array_intersect($array['a'], $array['b'], ...and so on for all elements...);
A loop could be used as well
$intersection = reset($array);
foreach ($array as $subarr) {
$intersection = array_intersect($intersection, $subarr);
}
print_r($intersection);

Modifying an array inside an array

So I need to modify the array in a memcached key-value pair. I need to remove one of the arrays inside the array. An example of what it looks like:
array(2) { [0]=> array(3) { ["username"]=> string(3) "Bob" ["id"]=> string(5) "14537" ["comment"]=> string(4) "cool"} [1]=> array(3) { ["username"]=> string(3) "Tom" ["id"]=> string(5) "14538" ["comment"]=> string(3) "yes"}}
If I know the values of username, id, and comment, how can I delete it? The generic queston: How can I delete array 0?
Considering the answer of doing a foreach loop, I tried
foreach($memcachedarray as $f){
if ($f['id'] == '14537'){
echo key($f);
}
}
But it spits out username
Edit- Ok
I searched some more and found I need to do this:
foreach($memcachedarray as $key => $f){
if ($f['id'] == '14537'){
echo $key;
}
}
That works!
If the Id's are unique across the system then you could use an associative array to store you data then unset the key, otherwise you would want to use a foreach loop to get the array key, then unset that key and recommit your new array back into memcache.

Get value from a array

update
how can I retrieve this value? I need to do that if I will write the value to my database.
array(3) {
[1]=> NULL
[2]=> array(2) {
[123]=>
int(123)
[122]=>
int(0)
}
[3]=> NULL
}
There is something missing in your output. I assume it looks something like:
// var_dump($array);
array(1) {
[0]=>
string(2) "39"
}
so you can access the value with $array[0]. Simple array access.
As arrays are the most important data structure in PHP, you should learn how to deal with them.
Read PHP: Arrays.
Update:
Regarding your update, which value do you want? You have a multidimensional array. This is what you will get:
$array[1] // gives null
$array[2] // gives an array
$array[2][123] // gives the integer 123
$array[2][122] // gives the integer 0
$array[3] // gives null
Maybe you also want (have) to loop over the inner array to get all values:
foreach($array[2] as $key => $value) {
// do something with $key and $value
}
As I said, read the documentation, it contains everything you need to know. Accessing arrays in PHP is not much different than in other programming languages.
The PHP manual contains a lot of examples, it is a pretty could documentation. Use it!
If your array is referenced as $myArray, you can get the string 39 via $myArray[0], i.e., this zeroth item.

Categories