---array $points----
Array
(
[0] => Array
(
[0] => 2011-10-02 05:30:00
[1] => 20
)
[1] => Array
(
[0] => 2011-10-04 09:30:00
[1] => 12
)
[2] => Array
(
[0] => 2011-10-01 13:30:00
[1] => 25
)
[3] => Array
(
[0] => 2011-10-03 02:30:00
[1] => 31
)
)
I have an array at above and would like to sort this array by time. Then I used the code as following to sort and result is correct. However, if I changed the code time[$key] = $val[0] to $time = $val[0], the result is wrong.
Is there anyone can explain this to me? Many thanks!
foreach($points as $key=>$val){
$time[$key] = $val[0];
array_multisort($time, SORT_ASC, $points);
}
array_multisort sorts more than one array at once. However, it works on an array of columns, so the foreach loop is needed to get a column of the times. After building up this list, you can then perform the multisort. The $points array is ordered according to the indices in $times, as per this example in the docs.
However, you don't need to perform the sort inside the foreach, as that means the sort happens 4 times (in your example). It only needs to happen once:
foreach ($points as $key => $val) {
$time[$key] = $val[0];
}
array_multisort($time, SORT_ASC, $points);
The function uasort() takes a comparison callback function. You can use this to compare two timestamps.
$arr = array(
array('2011-10-02 05:30:00','20'),
array('2011-10-04 09:30:00','12'),
array('2011-10-01 13:30:00','25'),
array('2011-10-03 02:30:00','31')
);
function timecomp($a,$b)
{
// Subtracting the UNIX timestamps from each other.
// Returns a negative number if $b is a date before $a,
// otherwise positive.
return strtotime($b[0])-strtotime($a[0]);
}
uasort($arr,'timecomp');
print_r($arr);
The above code will return
(
[1] => Array
(
[0] => 2011-10-04 09:30:00
[1] => 12
)
[3] => Array
(
[0] => 2011-10-03 02:30:00
[1] => 31
)
[0] => Array
(
[0] => 2011-10-02 05:30:00
[1] => 20
)
[2] => Array
(
[0] => 2011-10-01 13:30:00
[1] => 25
)
)
What you want to do is (basic idea):
foreach($points as $key=>$val){
$time[$val[1]] = $val[0]; // $time will be an array of [ point => time ] pairs
}
asort( $time ); // sorts the array and maintains indexes
After this you have an array of point => time pairs, sorted by time. To get just the points, for instance do
$points = array_keys( $time );
Related
i want to rearrange a simple multidimensional array.
Array
(
[pieces] => Array
(
[0] => 2
[1] => 9
)
[start] => Array
(
[0] => 0001
[1] => 9901
)
[end] => Array
(
[0] => 0002
[1] => 9909
)
[group] => Array
(
[0] => 0001-0100
[1] => 9901-9999
)
)
to
Array
(
[tokens] => Array
(
[0] => Array
(
[start] => 0001
[end] => 0002
[pieces] => 2
[group] => 0100
)
[1] => Array
(
[start] => 9901
[end] => 9909
[pieces] => 9
[group] => 9901-9999
)
)
)
I have tried something similar this:
$keys = array_keys($array);
foreach ($keys as $key => $val) {
foreach ($array as $k => $v){
foreach($array[$v] as $tk => $tv){
if($val == $k){
$new['tokens'][][$val] = $tv;
}
}
}
}
The numeric is the set of tokens which i prosted from my form,
Please can anyone explain me what i do wrong?
I am working some hours with different codes (i know the solution is very simple) but I am a little bit confused :/
Thank you very much!
BR KK
The Fourth Bird's solution is quite rigid in that it:
Requires an explicitly-defined key in the loop condition.
Enforces that the entire result has no more items than that one key has.
Assumes and enforces that the input keys are sequential and zero-indexed.
The below will work no matter what:
foreach( $array as $y => $inner ) {
foreach( $inner as $x => $value ) {
$new['tokens'][$x][$y] = $value;
}
}
Demo: https://3v4l.org/Rmdtd
Edit: I think it's worth preserving The Fourth Bird's explanation of the trouble with the posted code from his now-deleted answer:
You are trying to index into $array[$v], but $v in the case is one
of the sub arrays. According to the array
docs:
Arrays and objects can not be used as keys. Doing so will result in
a warning: Illegal offset type.
Make sure that you have error_reporting turned up to E_ALL while you're developing code so that you can see non-critical messages that indicate current and/or future problems.
i have a problem with array in php
example:
a=[1,2,3,4,5]
b=[2016, 2017, 2018, 2019, 2020]
I like to have following from a and b
c = [ [1,2016],[2,2017],[3,2018],[4,2019],[5,2020] ]
How to do that?Thank so much.
This code will set $c to the structure you wanted:
<?php
$a = [1,2,3,4,5];
$b = [2016, 2017, 2018, 2019, 2020];
$c = [];
foreach (array_keys($a) as $i) {
$c[] = [$a[$i], $b[$i]];
}
print_r($c);
The output is this:
Array
(
[0] => Array
(
[0] => 1
[1] => 2016
)
[1] => Array
(
[0] => 2
[1] => 2017
)
[2] => Array
(
[0] => 3
[1] => 2018
)
[3] => Array
(
[0] => 4
[1] => 2019
)
[4] => Array
(
[0] => 5
[1] => 2020
)
)
Or get it as you formatted it with json_encode($c):
[[1,2016],[2,2017],[3,2018],[4,2019],[5,2020]]
In case you don't like looping you can use array_merge_recursive if you do some manipulation with the arrays first.
Array_merge_recursive only works with associative arrays, so I make an array with A,B,C.. that I combine with the input arrays, this makes array_merge recursive work as expected.
The I use array_values to remove the associative keys.
Just as the other solutions, this expects equal lenghts of arrays.
$a=[1,2,3,4,5];
$b=[2016, 2017, 2018, 2019, 2020];
$keys = range("A", chr(64+count($a))); // [A,B,C,D,E]
$c = array_values(array_merge_recursive(array_combine($keys,$a),array_combine($keys,$b)));
Var_dump($c);
https://3v4l.org/qHCGI
I honestly think this is slower than looping on your arrays, maybe with a larger array times will be more equal.
This was mostly posted as "it works without looping" not as a quicker alternative.
Array
(
[0] => Array
(
[0] => 17
[1] => 111
)
[1] => Array
(
[0] => 17
[1] => 10
)
[2] => Array
(
[0] => 20
[1] => 111
)
)
I want to convert this array as:
array
(
[17]=>121
[20]=>111
)
is there any php array function which can do it easily. I know the other way, but want to know if any ready made function can do that or not??
Please Help.
Here I actually wanted to convert
[0] => Array
(
[0] => 17
[1] => 111
)
17 to key and take 111 as value then in next array
[1] => Array
(
[0] => 17
[1] => 10
)
do the same thing get first value 17 as key and add 10 into previous value 111
which is 121 and then
[2] => Array
(
[0] => 20
[1] => 111
)
take 20 as key and assign value 111 to that key so basically, I want first value as a key and second value as value and for all same keys I want to add values as I stated before.
I thought there might be any PHP ready-made function for that as I have seen there are lots of array processing functions available in PHP. Now, I realized there is no any such kind of function available. I can do my own custom code for this purpose but was looking for good logical solution.
No builtin function for that but it is a simple foreach loop. Assume your array is stored in variable $arr;
$return = array();
foreach ($arr as $a) {
$return[$a[0]] += $a[1];
}
echo "<pre>"; print_r($return);
if you are calling multiple times then you can easily write your own function
$arr[0]= array(17,111);
$arr[1]= array(17,10);
$arr[2]= array(20,111);
$return = subArr($arr);
echo "<pre>"; print_r($return);
function subArr($arr) {
$result = array();
foreach ($arr as $a) {
$result[$a[0]] += $a[1];
}
return $result;
}
I need to pass multiple array's in an indexed format to a cartesain function in order to calculate every permutation. This works when the code is:
$count = cartesian(
Array("GH20"),
Array(1,3),
Array(6,7,8),
Array(9,10)
);
I will not always know the length, number of arrays, or values so they are stored in another array "$total" which may look something like this:
Array (
[0] => Array
(
[0] => 1
[1] => 3
)
[1] => Array
(
[0] => 6
[1] => 7
[2] => 8
)
[2] => Array
(
[0] => 9
[1] => 10
)
)
I have tried implementing the user_call_back_function as per:
$count = call_user_func('cartesian', array($total));
However the array that then gets passed looks like this:
Array (
[0] => Array (
[0] => Array (
[0] => Array (
[0] => 1
[1] => 3
[2] => 4
)
[1] => Array (
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
[2] => Array (
[0] => 9
[1] => 10
)
)
)
)
Where am I going wrong, why is the array being buried further down in dimensions where it is not needed, and is this the reason why my cartesain function does no longer work?
Thanks, Nick
As requested, here is my cartesain function:
function cartesian() {
$_ = func_get_args();
if(count($_) == 0)
return array(array());
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
why is the array being buried further down in dimensions where it is not needed?
Simply because you are wrapping an array in another array when calling call_user_func.
$count = call_user_func('cartesian', array($total));
Perhaps you meant this:
$count = call_user_func('cartesian', $total);
is this the reason why my cartesain function does no longer work?
I don't know, you have not posted your cartesain, just an arrat called cartesain
EDIT as op updated the question.
If you are using PHP 5.6 you should be able to use the splat operator.
call_user_func("cartesain", ...$total);
Disclaimer, I have not tested this.
Arrays and Traversable objects can be unpacked into argument lists when calling functions by using the ... operator.
I have this multidimensional array:
Array
(
[0] => Array
(
[0] => 2012-02-26 07:15:00
)
[1] => Array
(
[0] => 2012-02-26 17:45:00
[1] => 2012-02-26 18:55:00
)
[2] => Array
(
[0] => 2012-02-26 18:55:00
[1] => 2012-02-26 17:45:00
)
[3] => Array
(
[0] => 2012-02-26 18:57:00
[1] => 2012-02-26 17:45:00
[2] => 2012-02-26 18:55:00
)
When I count subarrays I get this 1,2,2,3. How could I receive it in 3,2,2,1? I need to get for example last 3 subarrays with the highest subarray count (DESC, it means 3,2,2). How can I achieve this?
You can achieve it by utilizing usort function.
function cmp($a, $b){
return (count($b) - count($a));
}
usort($array, 'cmp');
$highest_3_sub_arrays = array_slice($array, 0, 3);
This might be what you seek:
natsort($sub_count);
$rev = array_reverse($sub_count);
$result = array_pad($rev, 3);
You might want to omit the actual sorting if the values you have are already in order.
$sizes=array();
foreach ($myarray as $k=>$v)
if (!is_array($v)) $sizes["$k"]=0;
else $sizes["$k"]=sizeof($v);
sort($sizes);
echo array_pop($sizes); //outputs 3
echo array_pop($sizes); //outputs 2
echo array_pop($sizes); //outputs 2
It seems to me that all of the other answers are working too hard. usort(), count(), and foreach() aren't necessary and when I tried natsort() it gave me: <b>Notice</b>: Array to string conversion in <b>[...][...]</b>.
rsort() will put the longest subarrays first.
Code:
$array=array(
["2012-02-26 18:55:00","2012-02-26 17:45:00"],
["2012-02-26 07:15:00"],
["2012-02-26 18:57:00","2012-02-26 17:45:00","2012-02-26 18:55:00"],
["2012-02-26 17:45:00","2012-02-26 18:55:00"]
);
$size=3; // modify this line to declare how many subarrays to capture
rsort($array); // sort the subarrays in DESC order
var_export(array_slice($array,0,$size)); // print the first n subarrays
Output:
array (
0 =>
array (
0 => '2012-02-26 18:57:00',
1 => '2012-02-26 17:45:00',
2 => '2012-02-26 18:55:00',
),
1 =>
array (
0 => '2012-02-26 18:55:00',
1 => '2012-02-26 17:45:00',
),
2 =>
array (
0 => '2012-02-26 17:45:00',
1 => '2012-02-26 18:55:00',
),
)
If you want to implement some additional sorting to break the length-ties (like between your two 2-element subarrays), then you will need to specify that in your question.