Multi array in php - php

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.

Related

How to merge subarray values and generate a 1-dimensional array of unique values?

How to get final unique array result from multiple array?
I have an array like this:
Array
(
[0] => Array
(
[0] => 8
[1] => 9
[2] => 7
)
[1] => Array
(
[0] => 7
[1] => 8
[2] => 9
[3] => 33
[4] => 21
)
[2] => Array
(
[0] => 11
[1] => 12
[2] => 33
[3] => 21
[4] => 9
[5] => 31
)
)
Expected result:
Array(
[0] => 7
[1] => 8
[2] => 9
[3] => 33
[4] => 21
[5] => 11
[6] => 12
[7] => 31
)
How to do that using php?
In your desired output indexes are same, you never achieve that. because same indexes are over-written by most recent values.
You can get like below:-
$final_array = array_unique(call_user_func_array('array_merge', $array)); //convert multi-dimensional array to single dimensional and remove duplicates
asort($final_array); // sort by value. this is optional
$final_array = array_values($final_array); // re-index final array and this is optional too
echo "<pre/>";print_r($final_array); // print final array
Output:- https://eval.in/752750
This takes three core PHP functions, sort, array_merg, and array_unique:
sort - sorts an array sent in by reference, meaning rather than returning a variable, it changes the order of the array itself.
array_merg - when combines with call_user_func_array will dynamically combine all the arrays together, however many there are.
array_unique - make sure there is only one of each element.
<?php
$arr = [ [8,9,7], [7,8,9,33,21], [11,12,33,21,9,31] ];
$merged = array_unique(call_user_func_array('array_merge', $arr));
sort($merged);
print_r($merged);
?>
Output:
Array
(
[0] => 7
[1] => 8
[2] => 9
[3] => 11
[4] => 12
[5] => 21
[6] => 31
[7] => 33
)
And here's it inside of eval.in:
https://eval.in/752793
This the way
<?php
$arr = [ [8,9,7], [7,8,9,33,21], [11,12,33,21,9,31] ];
$final = array();
foreach($arr as $child){
foreach($child as $value){
$final[] = $value;
}
}
$final = array_unique($final);
print_r($final);
?>
Demo : https://eval.in/752766
Output :
Array
(
[0] => 8
[1] => 9
[2] => 7
[6] => 33
[7] => 21
[8] => 11
[9] => 12
[13] => 31
)
Method #1: foreach loops with isset() that sort values by their first occurrence (Demo)(*this method seems to be the fastest of all)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
foreach($array as $sub){
foreach($sub as $v){
if(!isset($result[$v])){ // only add first occurence of a value
$result[$v]=$v;
}
}
}
var_export(array_values($result)); // re-index and print to screen
// condensed output: array(8,9,7,33,21,11,12,31)
Method #2: assign temporary keys which force value-overwriting to ensure no duplicates (Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
foreach($array as $sub){
foreach($sub as $v){
$result[$v]=$v; // force overwrite because duplicate keys cannot occur
}
}
sort($result); // sort and re-index
var_export($result); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)
Method #3: array_merge() with splat operator and array_unique() (Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
$unique=array_unique(array_merge(...$array)); // merge all subarrays
sort($unique); // sort and re-index
var_export($unique); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)
Method #4: unorthodox json_encode() & preg_match_all() (Demo) (Pattern Demo)
$array=[[8,9,7],[7,8,9,33,21],[11,12,33,21,9,31]];
$unique=preg_match_all('~\b(\d+)\b(?!.*\b\1\b)~',json_encode($array),$out)?$out[0]:[];
sort($unique); // sort and re-index
var_export($unique); // print to screen
// condensed output: array(7,8,9,11,12,21,31,33)

Sort a multi-dimensional array by the size of its sub-arrays

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.

questions on sort array by time in php

---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 );

How to sort a multi-dimensional array by values which are dates?

I am struggling with this. Sorting a multi-dimensional array by value based on dates. Here is a snippet of the array:
Array
(
[0] => Array
(
[clicks] => 14
[point] => 11 February 2011
)
[1] => Array
(
[clicks] => 1
[point] => 14 February 2011
)
[2] => Array
(
[clicks] => 8
[point] => 15 February 2011
)
[3] => Array
(
[clicks] => 0
[point] => 08 February 2011
)
I would like to sort it by date with the keys in the correct order. So in this case the 08 February 2011 should get key 0. I tried to make use of usort but that didn't go well as I couldn't even make use of the callback function in codeigniter which is another problem I am researching.
What is the most efficient way of doing this? My array can grow to 60 entries.
Thanks all for any help.
This custom sort should work:
function cmp($a, $b){
$l = strtotime($a['point']);
$r = strtotime($b['point']);
if($l == $r){
return 0;
}
return $l < $r ? -1 : 1;
}
usort($arr, "cmp");
Suppose, $data is your multi-dimensional array.
foreach ($data as $key => $row) {
$point[$key] = strtotime($row['point']);
}
// Sort the data with date ascending
array_multisort($point, SORT_ASC, $data);
See array_multisort function: http://php.net/manual/en/function.array-multisort.php (very useful for sorting multi-dimensional arrays)
Hope this helps.

PHP - Combine sub-arrays and sort by value?

This is what i've got now:
Array
(
[0] => Array
(
[0] => Array
(
[id] => 53
[date] => 18 Sep 2010 10:29
[user] => 52
[post] => ytiuy
)
[1] => Array
(
[id] => 55
[date] => 11 Sep 2010 11:14
[user] => 52
[post] => this is a test post :]
)
)
[1] => Array
(
[0] => Array
(
[id] => 56
[date] => 4 Sep 2010 03:19
[user] => 55
[post] => pppost :DD:D:D:D
)
)
)
I want to remove the first two "steps" in the array, and then sort the array by the 'date' value, like this:
Array
(
[0] => Array
(
[id] => 56
[date] => 4 Sep 2010 03:19
[user] => 55
[post] => pppost :DD:D:D:D
)
[1] => Array
(
[id] => 55
[date] => 11 Sep 2010 11:14
[user] => 52
[post] => this is a test post :]
)
[2] => Array
(
[id] => 53
[date] => 18 Sep 2010 10:29
[user] => 52
[post] => ytiuy
)
)
Any ideas?
Thanks a bunch, appreciate all help! :)
EDIT: I should also mention that the amount of arrayitems will not always be the same.
You should be able to use an accumulator pattern with the array_merge function to merge all the lower level arrays together.
$result = array();
foreach ($oldarray as $child)
{
$result = array_merge($result, $child);
}
Finally, you can use the user defined sort function to sort the whole thing.
An alternative to Don Kirby's solution would be to use an SplMaxHeap which would allow you to iterate and sort in one go:
class PostHeap extends SplMaxHeap
{
public function compare($post, $other)
{
return strtotime($post['date']) - strtotime($other['date']);
}
}
$postHeap = new PostHeap;
foreach($posts as $subArray) {
foreach($subArray as $post) {
$postHeap->insert($post);
}
}
The $postHeap would then contain the posts in descending date order, e.g. newest date first. You can use the code in the compare function if you want to use usort instead. The order will be ascending then though.
Do you have two arrays? Or more? Are they already sorted? If so, you can use that to combine them more efficiently. If not, you probably need to sort them first.
Roughly:
Sort your input arrays (optionally)
Scan your input arrays for the lowest value, copy that value into your new array, delete the value from the input array.
Repeat until all your input arrays are empty.
Of course, if you don't care about performance at all you could simply combine all the arrays and then sort that.
And for sorting you may want to use: http://www.php.net/manual/en/function.sort.php#99700
#Don Kirkby: Indeed: It's basically a mergesort, but it only works on already sorted arrays. If they're both unsorted you're probably better off with combining them and using quicksort instead.

Categories