Swapping elements in an array according to some criteria - php

I am trying to swap elements in my array according to some criteria.
For example, my array has "blocks" which have to move together, for example move +1 spot in the array.
// bubble sort
foreach ($cleanCard as $key=>$value) {
$cleanCard = handleGroupDirection('down', $value['groupID'], $cleanCard);
}
The $cleanCard array passed as parameter above looks like:
$cleanCard = array(
'0' => array(
'groupID' => 1,
'value' => 'T PHONE'
),
'1' => array
(
'groupID' => 1,
'value' => ''
),
'2' => array
(
'groupID' => 1,
'value' => 'C CELL'
),
'3' => null,
'4' => array
(
'groupID' => 0,
'value' => 'EMAIL'
)
);
As you can see in this array, the element at key #3 is empty, which means that the group should move down 1 spot (even a grouped item that has no value...). The empty key stays in the array.
The resulting array should look like:
Array
(
[0] =>
[1] => Array
(
[groupID] => 1
[value] => T PHONE
)
[2] => Array
(
[groupID] => 1
[value] =>
)
[3] => Array
(
[groupID] => 1
[value] => C CELL
)
[4] => Array
(
[groupID] => 0
[value] => EMAIL
)
)
My code looks like:
function handleGroupDirection($direction, $groupID, $card) {
$groupArr = array_map(function($field) { return $field['groupID']; }, $card);
$groupKeys = array_keys($groupArr, $groupID);
$firstFieldOfGroupIndex = $groupKeys[0];
$lastFieldOfGroupIndex = end($groupKeys);
switch ($direction) {
case 'down':
if ($lastFieldOfGroupIndex+1 >= count($card)) break;
if ($card[$lastFieldOfGroupIndex+1] == null) {
// move each field of the group down, starting
// from the last field in the group
for ($i = count($groupKeys); $i >= 0; $i--) {
$currentCardIndex = $groupKeys[$i];
$card[$currentCardIndex+1] = $card[$currentCardIndex];
}
// make the first field of the group null, the null spot we took is now basically going in front of the group
$card[$firstFieldOfGroupIndex] = null;
}
break;
}
return $card;
}
Haven't had success with this code yet.
Edit:
I get the notices:
NOTICE Undefined offset: 3 on line number 20
$currentCardIndex = $groupKeys[$i];
NOTICE Undefined index: on line number 21
$card[$currentCardIndex+1] = $card[$currentCardIndex];
And the current array I get is:
Array
(
[0] =>
[1] => Array
(
[groupID] => 1
[value] => T PHONE
)
[2] =>
[3] => Array
(
[groupID] => 1
[value] => C CELL
)
[4] => Array
(
[groupID] => 0
[value] => EMAIL
)
)
[2] Shouldn't be empty !

Related

get the sum value of specific key in given array and add row of count after specific completed index

Actual I get
Array
(
[0] => Array
(
[name] => person1
[value] => 11
)
[1] => Array
(
[name] => person2
[value] => 5
)
[2] => Array
(
[name] => person2
[value] => 5
)
[3] => Array
(
[name] => person4
[value] => 10
)
)
Actually i need
Array
(
[0] => Array
(
[name] => person1
[value] => 11
)
//here i want new row index 1 array
[1] => Array
(
[name] => total
[value] => 11 //this value is the sum of index 1
)
[2] => Array
(
[name] => person2
[value] => 5
)
[3] => Array
(
[name] => person2
[value] => 5
)
// here i want add new line index 4 array
[4] => Array
(
[name] => total
[value] => 10 //this value is the sum of index 2 and 3
)
[5] => Array
(
[name] => person4
[value] => 10
)
// here i want add new line index 6 array
[6] => Array
(
[name] => total
[value] => 10 //this value is the sum of index 5
)
)
may this help you i have tried some step making grouping but sum is not correct but code may help you
$a = Array
(
0 => Array
(
'name' => 'person1',
'value' => 11,
),
1 => Array
(
'name' => 'person2',
'value' => 5,
),
2 => Array
(
'name' => 'person2',
'value' => 5,
),
3 => Array
(
'name' => 'person4',
'value' => 10,
)
);
foreach($a as $c){
$d[]=$c['name'];
$e[]=$c['value'];
}
//print_r($d);
$group = array();
foreach($d as $key=>$val){
$group[$val][] = $e[$key];
}
// this loop for check the max number and count total price
$data = array();
$total = 0;
foreach($group as $key=>$val){
for($i=0;$i<count($val);$i++){
$data[]['name'] = $key;
$data[]['value'] = $val[$i];
$suma[] = $val[$i];
}
$sunmb =array_sum($suma);
$data[]['name'] = 'total';
$data[]['value'] = $sunmb;
}
print_r($data);
You can check code run here https://wtools.io/php-sandbox/b1LD

PHP: Get array value from other array in loop by condition

There are two arrays, one contains lists of playlists, the second contains their covers
Array with covers:
Array
(
[0] => Array
(
[id] => 110
[playlist_id] => 131
[video_key] => Jz4YS6oz
[user] => 20
[date] => 2019-08-09 12:21:40
)
[1] => Array
(
[id] => 109
[playlist_id] => 128
[video_key] => KoLwjBed
[user] => 20
[date] => 2019-08-09 11:37:50
)
)
Array with playlists:
Array
(
[0] => Array
(
[playlist_id] => 132
[playlist_title] => 222
[user] => 20
[date] => 2019-08-09 12:22:09
[cover] =>
[access] => 1
[playlist_videos] => 0
[playlist_featured] => 0
)
[1] => Array
(
[playlist_id] => 131
[playlist_title] => 111
[user] => 20
[date] => 2019-08-09 11:28:47
[cover] =>
[access] => 1
[playlist_videos] => 2
[playlist_featured] => 0
)
[2] => Array
(
[playlist_id] => 128
[playlist_title] => 333
[user] => 20
[date] => 2019-08-08 21:16:55
[cover] =>
[access] => 1
[playlist_videos] => 2
[playlist_featured] => 0
)
)
As can be seen from the code, both arrays contain the key [playlist_id]. It is necessary to somehow iterate the second array, so that the key [cover] gets the value [video_key] from the first array and the keys [playlist_id] match, if there is a playlist in the second array, but there is no cover from the first, then to the key [cover] must must contain null
I tried this varinat,
foreach($playlists as $pls){
foreach($covers as $cover){
if($cover['playlist_id'] == $pls['playlist_id']){
$output['list'][] = array(
'id' => $pls['playlist_id'],
'title' => $pls['playlist_title'],
'videos' => $pls['playlist_videos'],
'cover' => (isset($cover) && $cover['playlist_id'] == $pls['playlist_id']) ? $cover['video_key'] : NULL,
'date' => strtotime($pls['date']) * 1000,
'access' => $pls['access'],
);
}
}
}
Everything seems to be working well, but if the playlist does not have a cover, then the playlist is not displayed. If you remove the check in the second cycle, then in the final array there will be a number of elements equal to the product of the first and second arrays. For example, playlists 3, and covers 2, in the final array there will be 6 elements, some of which will be repeated ...
Using array_walk() you can do it easily. Using $filter scope we checked playlist_id from first array and replaced cover of second array by video_key of first array.
Example:
$filter = array_column($first_array, 'video_key', 'playlist_id');
array_walk($second_array, function (&$val) use ($filter) {
if (isset($filter[$val['playlist_id']])) $val['cover'] = $filter[$val['playlist_id']];
else unset($val['cover']);
});
echo '<pre>', print_r($second_array);
Working demo.
Update your loop. This should work:
foreach($playlists as $pls) {
$NewPlayList = array(
'id' => $pls['playlist_id'],
'title' => $pls['playlist_title'],
'videos' => $pls['playlist_videos'],
'date' => strtotime($pls['date']) * 1000,
'access' => $pls['access'],
'cover' => null
);
foreach($covers as $cover) {
if(isset($cover['playlist_id']) && ($cover['playlist_id'] == $pls['playlist_id'])) {
$NewPlayList['cover'] = $cover['video_key'];
}
}
$output['list'][] = $NewPlayList;
}
return array_map(function($playlist) {
$hasCover = array_filter($covers, function($c) use ($playlist){
return $c['playlist_id'] === $playlist['id'];
});
if (count($hasCover) > 0) {
return [
'id' => $playlist['playlist_id'],
'title' => $hasCover[0]['playlist_title'],
'videos' => $hasCover[0]['playlist_videos'],
'cover' => $hasCover[0]['playlist_videos']['cover'],
'date' => strtotime($hasCover[0]['playlist_videos']['date']) * 1000,
'access' => $hasCover[0]['playlist_videos']['access']
]
} else {
//playlist have no cover
return null;
}
} use ($covers));

Dynamically combine subsets of data with their header row, then group/merge/flatten datasets by a shared column

I have an array of arrays like this which I get from a server's response:
$data = array (
'data1' => array (
0 =>
array (
0 => 'ID',
1 => 'PinCode',
2 => 'Date',
),
1 =>
array (
0 => '101',
1 => '454075',
2 => '2012-03-03',
),
2 =>
array (
0 => '103',
1 => '786075',
2 => '2012-09-05',
),
),
'data2' => array (
0 =>
array (
0 => 'Balance',
1 => 'ID',
),
1 =>
array (
0 => '4533',
1 => '101',
)
),
'data3' => array (
0 =>
array (
0 => 'Active',
1 => 'ID',
),
1 =>
array (
0 => 'Yes',
1 => '101',
),
2 =>
array (
0 => 'No',
1 => '103',
),
),
);
On the above array I perform kind of a left join operation to get the final output below :
Array
(
[0] => Array
(
[ID] => 101
[PinCode] => 454075
[Date] => 2012-03-03
[Balance] => 4533
[Active] => Yes
)
[1] => Array
(
[ID] => 103
[PinCode] => 786075
[Date] => 2012-09-05
[Balance] => 0
[Active] => No
)
)
I will explain how I get the output.
In all the arrays data1 , data2 and data3 the first row is the name of the columns and the remaining rows contain the data for those columns.
Firstly I take the array whose length is maximum in the $data array. Hence from $data I first select data1 array as its length is 3.
Using the following code:
$data1=$data['data1'];
$columns_data1 = $data1[0];
for($i=1;$i<=(count($data1)-1);$i++)
{
$output_data1[] = array_combine($columns_data1,$data1[$i]);
}
echo print_r($output_data1);
I get the output $output_data1 like this :
Array
(
[0] => Array
(
[ID] => 101
[PinCode] => 454075
[Date] => 2012-03-03
)
[1] => Array
(
[ID] => 103
[PinCode] => 786075
[Date] => 2012-09-05
)
)
After this I perform the following operation on data2 and data3 arrays to make their length equal to that of data1 length - 1 i.e excluding the first row which contains column names.
$data2=$data['data2'];
$columns_data2 = $data2[0];
for($i=1;$i<=(count($data1)-1);$i++)
{
if($i<count($data2))
$output_data2[] = array_combine($columns_data2,$data2[$i]);
else
$output_data2[]=array_combine($columns_data2,array('0'=>'0','1'=>'0')); //add the value as 0 to the rows and make the length equal to that of data1. Here I've take index 0 and 1 because first row in data contains two index i.e Balance and ID.
}
echo print_r($output_data2);
This code gives the following output for data2 :
Array
(
[0] => Array
(
[Balance] => 4533
[ID] => 101
)
[1] => Array
(
[Balance] => 0
[ID] => 0
)
)
Similary for data3 :
$data3=$data['data3'];
$columns_data3 = $data3[0];
for($i=1;$i<=(count($data1)-1);$i++)
{
if($i<count($data3))
$output_data3[] = array_combine($columns_data3,$data3[$i]);
else
$output_data3[]=array_combine($columns_data3,array('0'=>'0','1'=>'0'));
}
echo "<pre>"; print_r($output_data3);
gives the output :
Array
(
[0] => Array
(
[Active] => Yes
[ID] => 101
)
[1] => Array
(
[Active] => No
[ID] => 103
)
)
Next I'll combine $output_data1 and $output_data2 :
$left_join_on = array_column($output_data2, "ID");
$first_leftjoin_output = array();
foreach($output_data1 as $values){
$key = array_search($values['ID'], $left_join_on);
if($key ===false){
$key = array_search(0, $left_join_on);
}
unset($output_data2[$key]['ID']);
$first_leftjoin_output[] = array_merge($values,$output_data2[$key]);
}
echo "<pre>"; print_r($first_leftjoin_output);
gives the output :
Array
(
[0] => Array
(
[ID] => 101
[PinCode] => 454075
[Date] => 2012-03-03
[Balance] => 4533
)
[1] => Array
(
[ID] => 103
[PinCode] => 786075
[Date] => 2012-09-05
[Balance] => 0 //added 0 to balance as ID 103 didn't existed in output_data2. just like a left join of sql
)
)
Next I'll do a join on $first_leftjoin_output and $output_data3
$left_join_on_next = array_column($output_data3, "ID");
$second_leftjoin_output = array();
foreach($first_leftjoin_output as $values){
$key = array_search($values['ID'], $left_join_on_next);
if($key ===false){
$key = array_search(0, $left_join_on_next);
}
unset($output_data3[$key]['ID']);
$second_leftjoin_output[] = array_merge($values,$output_data3[$key]);
}
echo "<pre>"; print_r($second_leftjoin_output);
This step gives the final output $second_leftjoin_output which I already mentioned at the beginning of the question.
Array
(
[0] => Array
(
[ID] => 101
[PinCode] => 454075
[Date] => 2012-03-03
[Balance] => 4533
[Active] => Yes
)
[1] => Array
(
[ID] => 103
[PinCode] => 786075
[Date] => 2012-09-05
[Balance] => 0
[Active] => No
)
)
Hence this way I left joined all the three arrays based on matching ID field.
As you can see I'm doing all this in a hard coded way.
If my $data array contains data4 then again I'll have add the code to get $third_leftjoin_output.
I want this process to be dynamic.
I want a dynamic solution such that I just have to pass the $data array and the name of the feild the left join is going to be based on.
Something like this :
$output = left_join_function($data,"ID");
and this function should return the mentioned output. Or any other better solution would be also very helpful.
I'm not able to figure out how this can be done in a neat way.
As you mentioned, you can use a function (https://www.php.net/manual/de/functions.user-defined.php)
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Example function.\n";
return $retval;
}
For you:
function dataJoinStep1($array)
{
// Do something with your array, left join etc.
return $array;
}
You can call the function in a loop (while/for/etc) dataJoinStep1($data)
My recommendation is robust enough to work on a dynamic number of data subsets, but it relies on the fact that all subsets are related by their ID value.
Iterate each group, separate the header data and combine it with subsequent rows within the group.
In the same loop, use first level keys to associate data from previously encountered groups (with the same first level key) and merge related data before pushing it into the result array. When finished iterating, call array_values() to re-index the result array.
Code: (Demo)
var_export(
array_values(
array_reduce(
$data,
function ($result, $group) {
$header = array_shift($group);
$idIndex = array_search('ID', $header);
foreach ($group as $row) {
$result[$row[$idIndex]] = array_merge(
$result[$row[$idIndex]] ?? [],
array_combine($header, $row)
);
}
return $result;
},
[]
)
)
);

PHP Filter array of arrays by multiple keys and group the arrays with matching keys

I have an array of arrays, and I want to filter that array by multiple key values, and group the arrays with matching keys if there are any. Example array:
Array
(
[0] => Array
(
[id] => 1
[value] => 11
[quantity] => 14
)
[1] => Array
(
[id] => 2
[value] => 11
[quantity] => 14
)
[2] => Array
(
[id] => 3
[value] => 22
[quantity] => 14
)
[3] => Array
(
[id] => 4
[value] => 22
[quantity] => 14
)
[4] => Array
(
[id] => 5
[value] => 23
[quantity] => 15
)
)
and let's say I want the arrays with matching value and quantity to be grouped in a new array
The desired output would be something like this:
Array
(
[11] => Array
(
[0] => Array
(
[id] => 1
[value] => 11
[quantity] => 14
)
[1] => Array
(
[id] => 2
[value] => 11
[quantity] => 14
)
)
[22] => Array
(
[0] => Array
(
[id] => 3
[value] => 22
[quantity] => 14
)
[1] => Array
(
[id] => 4
[value] => 22
[quantity] => 14
)
)
[23] => Array
(
[0] => Array
(
[id] => 5
[value] => 23
[quantity] => 15
)
)
)
I'm clueless on how to achieve this.
A simple foreach loop over your array to ceate a new array will suffice for this purpose
$new_arr = [];
foreach ($inArray as $arr ) {
$new_arr[$arr['value']][] = $arr;
}
// unset the original array if you are finished with it
// in case it is large and you could make better use
// of the memory for something else
unset($inArray);
If you want to group by the values of multiple keys of the inner arrays, you can join those values together to form the key in your result array.
foreach ($array as $item) {
// combine value and quantity, for example
$key = $item['value'] . '|' . $item['quantity'];
$result[$key][] = $item;
}
just pass an array References and a sort key
function sortBy(&$arr,$by){
$result=array();
foreach($arr as $value){
if(isset($value[$by]))
$result[$value[$by]][]=$value;
}
return $result;
}
Examples
$sorted=sortBy($yourArray,'value'); //by value
$sorted=sortBy($yourArray,'id'); //by Idx
$sorted=sortBy($yourArray,'quantity'); //quantity
You want to group the array keys passing, if I understood correctly.
I usually use the laravel collection library, because it's provided out of the box.
ALthoug, here's my contribution.
Let's try:
function groupArray( $array, $key, $remove = null )
{
$result = array();
foreach (array_unique(array_column($array, $key)) as $value) {
$result[$value] = array_map(function ( $item ) use ( $remove ) {
unset($item[$remove]);
return $item;
}, array_filter($array, function ( $item ) use ( $value, $key ) {
return $item[$key] === $value;
}));
}
return $result;
}
The above function does the job, first we get all the selected key values using the array_column function. THen we do a foreach in the array to filter the array data using the provided key and finally we remove the selected key, if necessary (just because the selected key will be the grouped array keys).
Usage:
$sample = array(
[
'id' => 1,
'value' => 11,
'quantity' => 14
],
[
'id' => 2,
'value' => 11,
'quantity' => 14
],
[
'id' => 3,
'value' => 22,
'quantity' => 14
],
[
'id' => 4,
'value' => 22,
'quantity' => 14
],
[
'id' => 5,
'value' => 23,
'quantity' => 14
],
);
$a = groupArray($sample, 'value', 'value');
$b = groupArray($sample, 'value');
$c = groupArray($sample, 'quantity');

Combine Arrays into One Multidimensional Array using PHP

I am trying to combine arrays into one single multidimensional array. There could be more than 5 arrays that needs to be combined so I need a code that will automatically combine all arrays no matter how many they are. I tried array_merge but it requires manual defining of arrays in comma formatted parameters.
The code to convert is:
Array
(
[id] => 1
[name] => Item 1
[slug] => item-slug-1
[parent] => 0
)
Array
(
[id] => 2
[name] => Item 2
[slug] => item-slug-2
[parent] => 1
)
Array
(
[id] => 3
[name] => Item 3
[slug] => item-slug-3
[parent] => 2
)
Array
(
[id] => 4
[name] => Item 4
[slug] => item-slug-4
[parent] => 3
)
Array
(
[id] => 5
[name] => Item 5
[slug] => item-slug-5
[parent] => 3
)
And this is how I would like it to look:
Array
(
[0] => Array
{
[id] => 1
[name] => Item 1
[slug] => item-slug-1
[parent] => 0
}
[1] => Array
{
[id] => 2
[name] => Item 2
[slug] => item-slug-2
[parent] => 1
}
[2] => Array
{
[id] => 3
[name] => Item 3
[slug] => item-slug-3
[parent] => 2
}
[3] => Array
{
[id] => 4
[name] => Item 4
[slug] => item-slug-4
[parent] => 3
}
[4] => Array
{
[id] => 5
[name] => Item 5
[slug] => item-slug-5
[parent] => 3
}
)
Here is how the arrays are generated:
I receive a response JSON from the server that looks like this:
[{"slug":"item-slug-1","name":"Item 1","id":1},{"slug":"item-slug-2","name":"Item 2","id":2},{"slug":"item-slug-3","name":"Item 3","id":3,"children":[{"slug":"item-slug-4","name":"Item 4","id":4},{slug":"item-slug-5","name":"Item 5","id":5}]}]
I decode the JSON then convert it to an array like this:
$categories_obj = json_decode( $_POST['order'] );
$categories_arr = json_decode(json_encode( $categories_obj ), true);
I created a function that walks through each item so it would be easier to insert into my database:
function walk_and_update($data, $parent = 0, $count = 0) {
if( is_array($data) ) {
$combine = array();
/* The arrays are generated here */
foreach( $data as $key => $row ) {
$formatted = array(
'id' => $row['id'],
'name' => $row['name'],
'slug' => $row['slug'],
'parent' => $parent
);
print_r( $formatted );
/* My SQL update is here */
if( isset( $row['children'] ) ) {
walk_and_update( $row['children'], $row['id'], $count );
}
}
}
}
Then I use the function like this:
walk_and_update( $categories_arr );
Like this:
$arr1 = Array(
'id' => 1,
'name' => 'Item 1',
'slug' => 'item-slug-1',
'parent' => 0);
$arr2 = Array(
'id' => 2,
'name' => 'Item 2',
'slug' => 'item-slug-2',
'parent' => 1);
$arr3 = Array(
'id' => 3,
'name' => 'Item 3',
'slug' => 'item-slug-3',
'parent' => 2);
$new_arr = array();
for($i=1;$i<=3;$i++) {
$var_name = 'arr'.$i;
array_push($new_arr,$$var_name);
}
echo "<pre>";print_r($new_arr);
Output:
Array
(
[0] => Array
(
[id] => 1
[name] => Item 1
[slug] => item-slug-1
[parent] => 0
)
[1] => Array
(
[id] => 2
[name] => Item 2
[slug] => item-slug-2
[parent] => 1
)
[2] => Array
(
[id] => 3
[name] => Item 3
[slug] => item-slug-3
[parent] => 2
)
)
you could make function to handle the array, then return expected array to multidimensional array.
can i know first, that the array you want to merging , did they produce one by one or just one time that can produce many array ?
//you could do this if your array produces one time only
$counter = 0;
$new_array=array();
foreach (your array as $key => $val)
{
$new_array[$counter]['id']= $val['id'];
$new_array[$counter]['name']= $val['name'];
$new_array[$counter]['slug']= $val['slug'];
$new_array[$counter]['parent'] = $val['parent'];
$counter++;
}
//if your array produces more than one time
function main ()
{
$data['counter']=0;
$data['newarray']=array();
$data = $this->mergin_array(your array,$data['counter'])
}
function merging_array(your array,$counter)
{
$data = array();
$counter_new = $counter;
foreach(your array as $key => $val)
{
$data['newarray'][$counter]['id'] = $val['id'];
$data['newarray'][$counter]['name'] = $val['name'];
$data['newarray'][$counter]['slug'] = $val['slug'];
$data['newarray'][$counter]['parent'] = $val['parent'];
$counter_new++;
}
$data['counter'] = $counter_new;
return $data;
}
so no matter how many you use , when you access the $data['newarray'] in your main function it will get you the combined for many array

Categories