If I have a matrix
[3,1,2,4]
[a,b,c,d]
And I need sort first row with usort key. But when I want reorder first array how do column moves at well
So output will be like this in this case described top
[1,2,3,4]
[b,c,a,d]
You can use array_multisort:
$x = [[3,1,2,4],['a','b','c','d']];
array_multisort($x[0], $x[1]);
var_dump($x);
Output:
array(2) {
[0]=>
array(4) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
}
[1]=>
array(4) {
[0]=>
string(1) "b"
[1]=>
string(1) "c"
[2]=>
string(1) "a"
[3]=>
string(1) "d"
}
}
I think what you're looking for is ksort.
Why list() method using two array (array of arrays) as values don't work (for one specific array ($subCategories) the list wrap in another array, the other array is output equals before list()).
list method:
list($subCategories, $subCategoriesName) = [$subCategories, $subCategoriesName]; //[array, array]
[$subCategories, $subCategoriesName] are the return of a function
$subCategories before list
array(4) {
[0]=>
array(3) {
["id"]=>
int(1)
["sub_category_name"]=>
string(14) "Industrilizado"
["category_id"]=>
int(1)
}
[1]=>
array(3) {
["id"]=>
int(2)
["sub_category_name"]=>
string(9) "In natura"
["category_id"]=>
int(1)
}
[2]=>
array(3) {
["id"]=>
int(3)
["sub_category_name"]=>
string(13) "Comida pronta"
["category_id"]=>
int(1)
}
[3]=>
array(3) {
["id"]=>
int(4)
["sub_category_name"]=>
string(11) "Desidratado"
["category_id"]=>
int(1)
}
}
$subCategories after list
array(1) {
[0]=>
array(4) {
[0]=>
array(3) {
["id"]=>
int(1)
["sub_category_name"]=>
string(14) "Industrilizado"
["category_id"]=>
int(1)
}
[1]=>
array(3) {
["id"]=>
int(2)
["sub_category_name"]=>
string(9) "In natura"
["category_id"]=>
int(1)
}
[2]=>
array(3) {
["id"]=>
int(3)
["sub_category_name"]=>
string(13) "Comida pronta"
["category_id"]=>
int(1)
}
[3]=>
array(3) {
["id"]=>
int(4)
["sub_category_name"]=>
string(11) "Desidratado"
["category_id"]=>
int(1)
}
}
edit:do not read the related topic, the answer below is clear and gives the solution, while the other topic just states the issue.
I have something weird here
My code looks like this:
var_dump($resultFlatTree);
foreach($resultFlatTree as &$element)
{
/*if(isset($element["action"]) && $element["action"] == "new")
{
//let's save the original ID so we can find the children
$originalID = $element["id"];
//now we get the object
$newObject = $setUpForDimension->createAnObject($dimension,$element,$customer);
$element['id'] = $newObject->getId();
echo "new";
//and let's not forget to change the parent_id of its children
$arrayFunctions->arrayChangingValues($resultFlatTree,"parent_id",$element['id'],$originalID);
$em->persist($newObject);
} */
}
$em->flush();
var_dump($resultFlatTree);
the code inside the foreach is commented to be sure that it's not what I'm doing that's changing the array.
here the array before the foreach:
array(3) {
[0]=>
array(10) {
["id"]=>
int(2)
["name"]=>
string(7) "Revenue"
["code"]=>
string(6) "700000"
["sense"]=>
string(2) "CR"
["lft"]=>
int(1)
["lvl"]=>
int(2)
["rgt"]=>
int(1)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00D"
["parent_id"]=>
int(1)
}
[1]=>
array(10) {
["id"]=>
int(3)
["name"]=>
string(7) "Charges"
["code"]=>
string(6) "600000"
["sense"]=>
string(2) "DR"
["lft"]=>
int(3)
["lvl"]=>
int(2)
["rgt"]=>
int(4)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00P"
["parent_id"]=>
int(4)
}
[2]=>
array(10) {
["id"]=>
int(4)
["name"]=>
string(6) "Energy"
["code"]=>
string(6) "606000"
["sense"]=>
string(2) "DR"
["lft"]=>
int(2)
["lvl"]=>
int(1)
["rgt"]=>
int(5)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00E"
["parent_id"]=>
int(1)
}
}
and then after:
array(3) {
[0]=>
array(10) {
["id"]=>
int(2)
["name"]=>
string(7) "Revenue"
["code"]=>
string(6) "700000"
["sense"]=>
string(2) "CR"
["lft"]=>
int(1)
["lvl"]=>
int(2)
["rgt"]=>
int(1)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00D"
["parent_id"]=>
int(1)
}
[1]=>
array(10) {
["id"]=>
int(3)
["name"]=>
string(7) "Charges"
["code"]=>
string(6) "600000"
["sense"]=>
string(2) "DR"
["lft"]=>
int(3)
["lvl"]=>
int(2)
["rgt"]=>
int(4)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00P"
["parent_id"]=>
int(4)
}
[2]=>
&array(10) {
["id"]=>
int(4)
["name"]=>
string(6) "Energy"
["code"]=>
string(6) "606000"
["sense"]=>
string(2) "DR"
["lft"]=>
int(2)
["lvl"]=>
int(1)
["rgt"]=>
int(5)
["root"]=>
int(1)
["$$hashKey"]=>
string(3) "00E"
["parent_id"]=>
int(1)
}
}
As you can see, the last element is now changed and is by reference.
This completely messes up the processes I do with the array afterward.
Is that normal behavior ?
How can I avoid it ?
When you pass by reference to a foreach statement, you really should read the docs :)
http://php.net/manual/en/control-structures.foreach.php
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element
?>
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().
Basically, it's saying that when you pass by ref, it will remain locked on the last item due to an internal pointer.
The second user-comment at 40 points:
"Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset()."
I cannot stress this point of the documentation enough! Here is a simple example of exactly why this must be done:
<?php
$arr1 = array("a" => 1, "b" => 2, "c" => 3);
$arr2 = array("x" => 4, "y" => 5, "z" => 6);
foreach ($arr1 as $key => &$val) {}
foreach ($arr2 as $key => $val) {}
var_dump($arr1);
var_dump($arr2);
?>
The output is:
array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(6) }
array(3) { ["x"]=> int(4) ["y"]=> int(5) ["z"]=> int(6) }
Notice how the last index in $arr1 is now the value from the last index in $arr2!
There are more comments which you will find interesting if you look for "reference" in that link.
tl;dr:
It's a bit funny/buggy/weird/un-patched.
Understand what the implications are as you write your code and make space for them.
I am generating an array of numbers based on an equation then rounding to the nearest 100.
After that I want to get rid of duplicates, array_unique seemed like the natural choice for this situation, but is not working as intended.
I created a small sample to demonstrate this.
The PHP code is as follows:
var_dump($amounts);
array_unique($amounts);
var_dump($amounts);
The result of which is:
array(6) {
[0]=>
float(200)
[1]=>
float(300)
[2]=>
float(300)
[3]=>
float(400)
[4]=>
float(500)
[5]=>
float(500)
}
array(6) {
[0]=>
float(200)
[1]=>
float(300)
[2]=>
float(300)
[3]=>
float(400)
[4]=>
float(500)
[5]=>
float(500)
}
Can someone shed some light on what is happening here please?
array_unique does not modify the array by reference. You'll need to catch the returned value:
$amounts = array_unique($amounts);
Note: the keys of the returned array may no longer be contiguous. If you want to make them contiguous again then you should use array_values.
Example:
$amounts = array(100, 200, 200, 200, 300, 400);
var_dump($amounts);
array(6) {
[0]=>
int(100)
[1]=>
int(200)
[2]=>
int(200)
[3]=>
int(200)
[4]=>
int(300)
[5]=>
int(400)
}
// Make the array unique
$amounts = array_unique($amounts);
var_dump($amounts);
array(4) {
[0]=>
int(100)
[1]=>
int(200)
[4]=>
int(300) // Notice the gap, indexes 2 and 3 don't exist.
[5]=>
int(400)
}
// Make the keys contiguous
$amounts = array_values($amounts);
var_dump($amounts);
array(4) {
[0]=>
int(100)
[1]=>
int(200)
[2]=>
int(300)
[3]=>
int(400)
}
I hate to beat a dead horse, but here goes. I have an Apache2 server running and I create my own php/html forms for in and output with mysql. Works great, I love it.
My problem is I have a huge array that I want to insert to MySQL but it needs to be sorted first (0<00). I've gone through the many Q & A covering the subject here and the code supplied works on a single array just fine. However, I need to loop through about 7000 sets and I'd like the output to be in original format but I have had no luck making that work as desired.
$data = array(
array(29,11,15,30,33),
array(30,11,25,18,02),
array(12,15,08,06,18),
array(17,20,03,21,02),
array(26,27,12,30,11),
array(05,25,34,11,16),
array(29,11,06,30,14),
array(05,26,12,18,33),
array(23,28,05,22,09),
array(05,36,31,32,27),
array(02,06,03,05,14)
);
An easy way to sort each sub array:
$data = array(
array(29,11,15,30,33),
array(30,11,25,18,02),
array(12,15,08,06,18),
array(17,20,03,21,02),
array(26,27,12,30,11),
array(05,25,34,11,16),
array(29,11,06,30,14),
array(05,26,12,18,33),
array(23,28,05,22,09),
array(05,36,31,32,27),
array(02,06,03,05,14)
);
foreach($data as &$value){ // Mind the & byref value
sort($value);
}
var_dump($data);
// $data is now sorted over here
The output:
array(11) {
[0]=>
array(5) {
[0]=>
int(11)
[1]=>
int(15)
[2]=>
int(29)
[3]=>
int(30)
[4]=>
int(33)
}
[1]=>
array(5) {
[0]=>
int(2)
[1]=>
int(11)
[2]=>
int(18)
[3]=>
int(25)
[4]=>
int(30)
}
[2]=>
array(5) {
[0]=>
int(0)
[1]=>
int(6)
[2]=>
int(12)
[3]=>
int(15)
[4]=>
int(18)
}
[3]=>
array(5) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
int(17)
[3]=>
int(20)
[4]=>
int(21)
}
[4]=>
array(5) {
[0]=>
int(11)
[1]=>
int(12)
[2]=>
int(26)
[3]=>
int(27)
[4]=>
int(30)
}
[5]=>
array(5) {
[0]=>
int(5)
[1]=>
int(11)
[2]=>
int(16)
[3]=>
int(25)
[4]=>
int(34)
}
[6]=>
array(5) {
[0]=>
int(6)
[1]=>
int(11)
[2]=>
int(14)
[3]=>
int(29)
[4]=>
int(30)
}
[7]=>
array(5) {
[0]=>
int(5)
[1]=>
int(12)
[2]=>
int(18)
[3]=>
int(26)
[4]=>
int(33)
}
[8]=>
array(5) {
[0]=>
int(0)
[1]=>
int(5)
[2]=>
int(22)
[3]=>
int(23)
[4]=>
int(28)
}
[9]=>
array(5) {
[0]=>
int(5)
[1]=>
int(27)
[2]=>
int(31)
[3]=>
int(32)
[4]=>
int(36)
}
[10]=>
&array(5) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
int(5)
[3]=>
int(6)
[4]=>
int(14)
}
}
EDIT
Or like #JREAM suggest, you can use array_walk:
array_walk($data, sort);