PHP: how to sort an array by keys numerically? - php

Even though I have read the PHP documentation and this looks like to be a FAQ, it's still giving me some headache.
I have an array like this which holds the months of the year:
[12] => december
[4] => april
[3] => march
[6] => june
[7] => july
[10] => october
...and so on
The order is not as it should be. I want to reorder the keys numerically. I can swap the keys with values if I want, but while each numerical value will match the corresponding month, they will never be in order. So I thought of putting these in order via PHP.
I have tried with $calendar = ksort( $myarray );
But If I try to print $calendar, I will only get bool=true or array with a single key and "1" as value... I was planning to use the ksort result in a foreach later, but I can't.
What I'm droing wrong?

No .. just use:
ksort($myarray);
print_r($myarray)
Codepad example
ksort() sorts an array by key, maintaining key to data correlations, returns TRUE on success or FALSE on failure, if you associate the $calendar with ksort() you will have what ksort returns.

ksort($arr);
foreach ($arr as $key => $val)
{
echo "$key = $val\n";
}

Related

Unable to convert array according to date time value in php

I have a array named $itemIds and it consists of the following datas. The key is the items id and the value is the date time that can be converted to a readable date.What I want to do is simply sort the order of the array according to the value (time). I'm totally new to php and some examples or tips would be great ! I would love to hear from you.
Array
(
[10477] => 1508898726
[10549] => 1508898744
[10891] => 1508898752
)
If I use this code I get the following data from the print_r.
if (isset($itemIds)) {
$time = array();
foreach ($itemIds as $key => $val) {
print_r($key.'=>'.date('m/d/Y H:i:s', $val));
}
}
The problem starts from here.I want to sort(asc & desc) the $itemsIds according to the date time.
10477 => 10/25/2017 11:32:06
10549 => 10/25/2017 11:32:24
10891 => 10/25/2017 11:32:32
I want to sort the data then use array_keys($shopIds) to change it like the following data
Array
(
[0] => 10477
[1] => 10549
[2] => 10891
)
I think the easier approach would be to sort the data and then flip it so the keys are values. If you look at your data you are initially dealing with actual timestamps from what I can see. Use them, don't change them to strings. I say this because you are just causing yourself to do extra work without any reason and introducing a layer of complexity that is not needed. Instead I would do the following:
$array = [
10477 => 1508898726,
10549 => 1508898744,
10891 => 1508898752,
];
arsort($array);
$sorted_array = array_values(array_flip($array));
This is easy to read and does not involve the extra function. The result you are left with is:
Array
(
[0] => 10477
[1] => 10549
[2] => 10891
)
A little explanation:
I am using arsort() or asort() (based on the direction you want to sort) in order to sort based on the values in the array.
Then I use array_flip() on the array in order to swap the keys and values.
And last I am using array_keys() to reset the indexes in the array and maintain its sort.
Hope this helps!

PHP Reverse Sort Associative Array arsort() Not Working?

Is anyone able to point me in the right direction for why i cannot get arsort() to work on the following please:
$d=array();
$d['y'][0]['year'] = 2000;
$d['y'][1]['year'] = 2001;
$d['y'][2]['year'] = 2002;
$d['y'][3]['year'] = 2003;
$d['y'][4]['year'] = 2004;
$d['y'][5]['year'] = 2005;
arsort($d['y']);
$i=0
foreach ($d['y'] as $value){
$i++;
echo $d['y'][$i]['year'];
}
It just echo's out in the order 0,1,2,3,4 etc... I can't seem to find what i'm missing here?
Thanks
Your code is correct, but you make an error when you print.
By referring to a value indexed as $d['y']['5']['year'], the result will always be 2005. Accordingly, the foreach displays the years in ascending order. Try instead:
foreach($d['y'] as $value) {
echo $value['year'];
}
and you will see that your array is in reverse order.
(Don't use variable $i in the foreach cycle)
Riccardo pointed me in the right direction, I found that i needed to use:
echo $value['year'];
and not
echo $d['y'][$i]['year'];
As the $i counter was calling the index number directly rather than using the sorted array when looping.
Since arsort() maintains the key associations, the reordered multidimensional array will have the zeroth element last and element 5 appearing first. Using a foreach-loop could leave the code prone to failing to display the reverse sorted array, if variable $i is initially set to zero. To avoid such an inadvertent error as well as improve performance and simplify the code, one could replace the foreach-loop, as follows:
<?php
function showData($value,$key){
echo "$value\n";
}
array_walk_recursive( $d, 'showData');
array_walk_recursive(), as its name suggests, recursively traverses an array to find the data. The callback allows one to easily access and display values.
See demo
It's because arsort() will keep the key. You can check the manual here.
So after arsort() $d is like below, but you print in a reverse way which make it like not have been sorted. Check the live demo.
Array
(
[y] => Array
(
[5] => Array
(
[year] => 2005
)
[4] => Array
(
[year] => 2004
)
[3] => Array
(
[year] => 2003
)
[2] => Array
(
[year] => 2002
)
[1] => Array
(
[year] => 2001
)
[0] => Array
(
[year] => 2000
)
)
)

PHP - Why doesn't array_multisort function sort correctly?

please view the following code with 2 arrays. i use multisort function with sort flags for ascending and numeric then display. as you can see in the output that array 2 starts with 100 when it should be last. please explain what is causing this and how to sort it correctly. thank you.
<?php
$array1 = array(1,7,10,6);
$array2 = array(100,20,25,10);
array_multisort($array1, SORT_ASC, SORT_NUMERIC, $array2);
print_r($array1);
echo "<br>";
print_r($array2);
?>
output:
Array ( [0] => 1 [1] => 6 [2] => 7 [3] => 10 )
Array ( [0] => 100 [1] => 10 [2] => 20 [3] => 25 )
Ah, yes, array_multisort is a bit tricky to understand the first time round.
Basically the sort is lexicographical, a fancy word meaning that the first array is sorted and the second arrays elements are ordered according to the first array.
Look at your first (output) array and see the order and map it to the initial second array and you'll see whats happening.
So the second array you take the 1st, 4th , 2nd and 3rd elements.
If you just want plain sorting for multiple arrays then just do them one by one or over a loop.

Difference between array_filter() and array_map()? [duplicate]

This question already has answers here:
Difference between array_map, array_walk and array_filter
(5 answers)
Closed 2 years ago.
I looked into the similar topics in web as well stack overflow, but could get this one into my head clearly. Difference between array_map, array_walk and array_filter
<?php
error_reporting(-1);
$arr = array(2.4, 2.6, 3.5);
print_r(array_map(function($a) {
$a > 2.5;
},$arr));
print_r(array_filter($arr, function($a){
return $a > 2.5;
}));
?>
The above code returns me a filtered array whose value is > 2.5. Can i achieve what an array_filter does with an array_map?.
All three, array_filter, array_map, and array_walk, use a callback function to loop through an array much in the same way foreach loops loop through an $array using $key => $value pairs.
For the duration of this post, I will be referring to the original array, passed to the above mentioned functions, as $array, the index, of the current item in the loop, as $key, and the value, of the current item in the loop, as $value.
array_filter is likened to MySQL's SELECT query which SELECTs records but doesn't modify them.
array_filter's callback is passed the $value of the current loop item and whatever the callback returns is treated as a boolean.
If true, the item is included in the results.
If false, the item is excluded from the results.
Thus you might do:
<pre><?php
$users=array('user1'=>array('logged_in'=>'Y'),'user2'=>array('logged_in'=>'N'),'user3'=>array('logged_in'=>'Y'),'user4'=>array('logged_in'=>'Y'),'user5'=>array('logged_in'=>'N'));
function signedIn($value)
{
if($value['logged_in']=='Y')return true;
return false;
}
$signedInUsers=array_filter($users,'signedIn');
print_r($signedInUsers);//Array ( [user1] => Array ( [logged_in] => Y ) [user3] => Array ( [logged_in] => Y ) [user4] => Array ( [logged_in] => Y ) )
?></pre>
array_map on the other hand accepts multiple arrays as arguments.
If one array is specified, the $value of the current item in the loop is sent to the callback.
If two or more arrays are used, all the arrays need to first be passed through array_values as mentioned in the documentation:
If the array argument contains string keys then the returned array
will contain string keys if and only if exactly one array is passed.
If more than one argument is passed then the returned array always has
integer keys
The first array is looped through and its value is passed to the callback as its first parameter, and if a second array is specified it will also be looped through and its value will be sent as the 2nd parameter to the callback and so-on and so-forth for each additional parameter.
If the length of the arrays don't match, the largest array is used, as mentioned in the documentation:
Usually when using two or more arrays, they should be of equal length
because the callback function is applied in parallel to the
corresponding elements. If the arrays are of unequal length, shorter
ones will be extended with empty elements to match the length of the
longest.
Each time the callback is called, the return value is collected.
The keys are preserved only when working with one array, and array_map returns the resulting array.
If working with two or more arrays, the keys are lost and instead a new array populated with the callback results is returned.
array_map only sends the callback the $value of the current item not its $key.
If you need the key as well, you can pass array_keys($array) as an additional argument then the callback will receive both the $key and $value.
However, when using multiple arrays, the original keys will be lost in much the same manner as array_values discards the keys.
If you need the keys to be preserved, you can use array_keys to grab the keys from the original array and array_values to grab the values from the result of array_map, or just use the result of array_map directly since it is already returning the values, then combine the two using array_combine.
Thus you might do:
<pre><?php
$array=array('apple'=>'a','orange'=>'o');
function fn($key,$value)
{
return $value.' is for '.$key;
}
$result=array_map('fn',array_keys($array),$array);
print_r($result);//Array ( [0] => a is for apple [1] => o is for orange )
print_r(array_combine(array_keys($array),$result));//Array ( [apple] => a is for apple [orange] => o is for orange )
?></pre>
array_walk is very similar to foreach($array as $key=>$value) in that the callback is sent both a key and a value. It also accepts an optional argument if you want to pass in a 3rd argument directly to the callback.
array_walk returns a boolean value indicating whether the loop completed successfully.
(I have yet to find a practical use for it)
Note that array_walk doesn't make use of the callback's return.
Since array_walk returns a boolean value, in order for array_walk to affect something,
you'll need to reference &$value so you have that which to modify or use a global array.
Alternatively, if you don't want to pollute the global scope, array_walk's optional 3rd argument can be used to pass in a reference to a variable with which to write to.
Thus you might do:
<pre><?php
$readArray=array(1=>'January',2=>'February',3=>'March',4=>'April',5=>'May',6=>'June',7=>'July',8=>'August',9=>'September',10=>'October',11=>'November',12=>'December');
$writeArray=array();
function fn($value,$key,&$writeArray)
{
$writeArray[$key]=substr($value,0,3);
}
array_walk($readArray,'fn',&$writeArray);
print_r($writeArray);//Array ( [1] => Jan [2] => Feb [3] => Mar [4] => Apr [5] => May [6] => Jun [7] => Jul [8] => Aug [9] => Sep [10] => Oct [11] => Nov [12] => Dec )
?></pre>
array_filter returns the elements of the original array for which the function returns true.
array_map returns an array of the results of calling the function on all the elements of the original array.
I can't think of a situation where you could use one instead of the other.
array_map Returns an array containing all the elements of array after applying the callback function to each one.
for example:
$a=array("a","bb","ccd","fdjkfgf");
$b = array_map("strlen",$a);
print_r($b);
//output
Array
(
[0] => 1 //like strlen(a)
[1] => 2 //like strlen(bb)
[2] => 3 //like strlen(ccd)
[3] => 7 //like strlen(fdjkfgf)
)
whereas array_filter return only those elements of array for which the function is true
example: remove "bb" value from array
function test_filter($b)
{
if($b=="bb")
{
return false;
}
else
{
return true;
}
}
$a=array("a","bb","ccd","fdjkfgf");
$b = array_filter($a,"test_filter");
print_r($b);
//output
Array
(
[0] => a //test_filter() return true
[2] => ccd //test_filter() return true
[3] => fdjkfgf //test_filter() return true
)
array_filter works without a callable (function) being passed, whereas for array_map it is mandatory.
e.g.
$v = [true, false, true, true, false];
$x = array_filter($v);
var_dump($x);
array(3) { [0]=> bool(true) [2]=> bool(true) [3]=> bool(true) }
array_walk changes the actual array passed in, whereas array_filter and array_map return new arrays, this is because the array is passed by reference.
array_map has no collateral effects while array_map never changes its arguments.
The resulting array of array_map/array_walk has the same number of
elements as the argument(s); array_filter picks only a subset of the
elements of the array according to a filtering function. It does
preserve the keys.
Example:
<pre>
<?php
$origarray1 = array(2.4, 2.6, 3.5);
$origarray2 = array(2.4, 2.6, 3.5);
print_r(array_map('floor', $origarray1)); // $origarray1 stays the same
// changes $origarray2
array_walk($origarray2, function (&$v, $k) { $v = floor($v); });
print_r($origarray2);
// this is a more proper use of array_walk
array_walk($origarray1, function ($v, $k) { echo "$k => $v", "\n"; });
// array_map accepts several arrays
print_r(
array_map(function ($a, $b) { return $a * $b; }, $origarray1, $origarray2)
);
// select only elements that are > 2.5
print_r(
array_filter($origarray1, function ($a) { return $a > 2.5; })
);
?>
</pre>
Result:
Array
(
[0] => 2
[1] => 2
[2] => 3
)
Array
(
[0] => 2
[1] => 2
[2] => 3
)
0 => 2.4
1 => 2.6
2 => 3.5
Array
(
[0] => 4.8
[1] => 5.2
[2] => 10.5
)
Array
(
[1] => 2.6
[2] => 3.5
)

Php two different array with same keys

I am new to php and still learning the language,
let say I have two array
For Example
Array
(
[house_id] => 6
[name] => Lake Villa
[floor] => 5
[unit] => 25
)
Array
(
[house_id] => 6
[name] => Lake Villa
[floor] => 5
[unit] => 25
[parking_id] => 9
[resident_count] => 4
)
How do i get the keys of 1st array onto second, what i am saying is, i just need house_id, name, floor, unit from second array and discard rest of the information.
However, they key is not same and dynamic, which means the first array key whatever returned is also present on second but with additional information. The information above is just an example and the keys might varies but whatever key on first array contains on second array too.
I tried this, but isn't working:
foreach($arr1 as $k=>$v) {
foreach($arr2 as $j=>$w) {
if(isset($arr2[$k]))
$arr[$k] = $w;
}
}
You could use array_intersect_key, to merge the arrays.
$newArray = array_intersect_key($array2, $array1);
Use array_intersect_key().
array_intersect_key() returns an array containing all the entries of
array1 which have keys that are present in all the arguments.
Code
var_dump(array_intersect_key($array1, $array2));
foreach($arr2 as $key=>$val){
if(!array_key_exists($key,$arr1))
unset($arr2[$key]);
}
change condition from
if(isset($arr2[$k]))
to
if($arr1[$k] == $arr2[$j]) // it will work.
and isset is used for checking the variable is set or not.
Try this:
foreach($arr2 as $k=>$v) {
//Check if key is in first array
if(!isset($arr1[$k])) {
//Key not in first array, remove from second array.
unset($arr2[$k]);
}
}
try this
$result_array = array_intersect_key($arr2, $arr1);

Categories