Racking my brain on this, found many examples of similar situations however the solutions don't seem to match up.
I have two arrays being built as the result of SQL queries on different databases.
One is coming through formatted as such:
$data = array([$sku] => array(['LocalSKU'] => $sku,
['Price'] => $msrp,
['Price2'] => $wholesale,
['Price3'] => $distributor,
['Price4'] => $map))
The other array is formatted as such:
$matchme = array([0] => array(['entity_id'] => $entity_id,
['sku'] => $sku,
['type_id'] => $type_id))
Currently, I can get the individual data to match up via:
echo $matchme[0]['sku'];
echo $matchme[0]['entity_id'];
echo $matchme[0]['type_id'];
echo $data[$matchme[0]['sku']]['Price'];
echo $data[$matchme[0]['sku']]['Price2'];
echo $data[$matchme[0]['sku']]['Price3'];
echo $data[$matchme[0]['sku']]['Price4'];
However, when I try and merge the matching rows in both arrays, I get an empty array. The $data array contains 74 unique $sku, and $matchme is the result of checking those $sku's against a database and returning an array with 61 elements. So, the combined array should have 61 elements with matched pricing data based on the $sku.
How I am attempting to build the combined array is below, can anyone point me towards what I am doing wrong?
foreach($matchme as $key){
if(in_array($matchme[$key]['sku'], $data)){
$matched_luggage[$matchme[$key]['sku']][] = array(
'sku' => $matchme[$key]['sku'],
'entity_id' => $matchme[$key]['entity_id'],
'type_id' => $matchme[$key]['type_id'],
'MSRP' => $data[$matchme[$key]['sku']]['Price'],
'Wholesale' => $data[$matchme[$key]['sku']]['Price2'],
'Distributor' => $data[$matchme[$key]['sku']]['Price3'],
'MAP' => $data[$matchme[$key]['sku']]['Price4']
);
}
}
In the above example, evaluate $key as 0, and the value of ['sku'] are matching.
------------------------Edited-------------------------
Per request, here is the result of print_r($data) truncated for space:
Array
(
[12PK-TITANIUM-CR123A] => Array
(
[LocalSKU] => 12PK-TITANIUM-CR123A
[Price] => 11.76
[Price2] => 10.32
[Price3] => 0
[Price4] => 0
)
[AA-CLAMSHELL] => Array
(
[LocalSKU] => AA-CLAMSHELL
[Price] => 0.25
[Price2] => 0
[Price3] => 0
[Price4] => 0
)
[AAA-CLAMSHELL] => Array
(
[LocalSKU] => AAA-CLAMSHELL
[Price] => 0.25
[Price2] => 0
[Price3] => 0
[Price4] => 0
)
[AE-AEL280PI] => Array
(
[LocalSKU] => AE-AEL280PI
[Price] => 0
[Price2] => 0
[Price3] => 0
[Price4] => 0
) )
Per request, here is the result of print_r($matchme) truncated for space:
Array
(
[0] => Array
(
[entity_id] => 693
[sku] => 12PK-TITANIUM-CR123A
[type_id] => simple
)
[1] => Array
(
[entity_id] => 2596
[sku] => AE-AEL480HL
[type_id] => simple
)
[2] => Array
(
[entity_id] => 2597
[sku] => AE-AEL600-T6
[type_id] => simple
)
[3] => Array
(
[entity_id] => 2598
[sku] => AE-AEWL2
[type_id] => simple
) )
Per request, here is the desired result of $matched_luggage:
$matched_luggage = array( [12PK-TITANIUM-CR123A] => array([sku] => 12PK-TITANIUM-CR123A,
[entity_id] => 693,
[type_id] => simple,
[Price] => 11.76,
[Price2] => 10.32,
[Price3] => 0,
[Price4] => 0))
with an additional array per matched sku.
Try this:
foreach ($matchme as $arrProduct) {
if (isset($data[$arrProduct['sku']])) {
$arrMerged[$arrProduct['sku']]=array_merge($arrProduct, $data[$arrProduct['sku']]);
}
}
print_r($arrMerged);
The reason your code doesn't work is here:
if(in_array($matchme[$key]['sku'], $data)) [...]
What in_array() does is tell you whether your needle (in your case the SKU string) exists as a value of array haystack (in your case, $data). You are essentially trying to match a string to an array, rather than another string.
What you really want is just to match the SKU string to the key of $data, for which isset() is probably the simplest approach.
Assuming your first array as $first and second array as $second
foreach ($first as $key => $each) {
foreach ($second as $secondeach) {
if($secondeach['sku'] == $key) {
$first[$key] = array_merge($first[$key], $secondeach);
// unset since you do not want LocalSKU value anymore.
unset($first[$key]['LocalSKU']);
}
}
}
$first is your array you wanted.
Related
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));
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;
},
[]
)
)
);
I am working on a php project. I am stuck at this point.
Here is the array that I have.
[text_numeric] => Array
(
[text] => Numeric field fillable by user
[parameters] => Array
(
[prefix] => 1
[price] => 1
[sku] =>
[quantity] =>
[weight] =>
[min_value] => 1
[max_value] => 1
)
[operand] => Array
(
[op_fix_discount] => 1
[op_fix_recharge] => 1
[op_per_unit] => 1
[op_percentage] =>
)
)
[checkbox] => Array
(
[text] => Checkbox attributes
[parameters] => Array
(
[prefix] => 1
[price] => 1
[sku] => 1
[quantity] => 1
[weight] => 1
[min_value] =>
[max_value] =>
)
[operand] => Array
(
[op_fix_discount] => 1
[op_fix_recharge] => 1
[op_per_unit] =>
[op_percentage] => 1
)
)
I want to get all the values from this array with key value "text" in another array.
Like this:
Array
(
[0]=>Numeric field fillable by user
[1]=>Checkbox attributes
)
It could have been great if you had show us your efforts to achieve that but since you are new here is the codez. You can simply get it using a foreach loop,
$new_array = array();
foreach($your_array as $k=>$row){
$new_array[$k] = $row['text'];
}
print_r($new_array);
You can also use array_map,
function getTextField($a) {
return $a['text'];
}
$texts = array_map('getTextField', $your_array);
print_r($texts);
I have two arrays
First array named "$periods" and second array named "$groupExport" like below.
First Array - $periods
Array
(
[0] => 201308
[1] => 201309
[2] => 201310
)
Second Array - $groupExport
Array
(
[0] => Array
(
[GroupCode] => 111
[GroupDesc] => Crop Production
[201308] => 1.5500
[201309] => 240.4200
[201310] => 41.2110
)
[1] => Array
(
[GroupCode] => 112
[GroupDesc] => Animal Production
[201309] => 3.1800
)
[2] => Array
(
[GroupCode] => 115
[GroupDesc] => Agriculture, Forestry Support
[201308] => 234.0400
[201310] => 343.0200
)
)
I have tried atleast 5-6 different code ideas, it does not yields the below output. I want the output like below, so that I can display the resultset in table format according to the header GroupCode, GroupDesc, 201308, 201309 & 201310. Could anyone help me to resolve this?
Output
Array
(
[0] => Array
(
[GroupCode] => 111
[GroupDesc] => Crop Production
[201308] => 1.5500
[201309] => 240.4200
[201310] => 41.2110
)
[1] => Array
(
[GroupCode] => 112
[GroupDesc] => Animal Production
[201308] => 0
[201309] => 3.1800
[201310] => 0
)
[2] => Array
(
[GroupCode] => 115
[GroupDesc] => Agriculture, Forestry Support
[201308] => 234.0400
[201309] => 0
[201310] => 343.0200
)
)
Loop through the $groupExport array and on each iteration, loop through the sub-array and check if the each one of the period index exists. If they don't, initialize them with 0.
foreach ($groupExport as & $export) {
foreach ($periods as $period) {
if (!isset($export[$period])) {
$export[$period] = 0;
}
}
}
Note the & before $export. It means we're passing the array by reference — it's modifying $groupExport on each iteration.
Demo
Note: This will mutate the original array. If you want to produce a new array, #AmalMurali's solution is superior.
Here's an alternate solution that uses some of PHP's built-in functions:
$keys = array_fill_keys($periods, 0);
array_walk($groupExport, function (&$item, $key, $keys) {
$item += $keys;
}, $keys);
Here's a demonstration at IDEOne.com.
Explanation
$keys = array_fill_keys($periods, 0);
This converts your array of periods into a new array where the value from the original array is now the key, and the value is 0.
array_walk($groupExport, function (&$item, $key, $keys) {
$item += $keys;
}, $keys);
We walk over each element of the array $groupExport, and apply a function to each member. We pass each array element as a reference to our user defined function, which allows us to manipulate it directly.
Finally, we add $keys to $item which essentially merges the two arrays while maintaining key associations.
Output
Array
(
[0] => Array
(
[GroupCode] => 111
[GroupDesc] => Crop Production
[201308] => 1.55
[201309] => 240.42
[201310] => 41.211
)
[1] => Array
(
[GroupCode] => 112
[GroupDesc] => Animal Production
[201309] => 3.18
[201308] => 0
[201310] => 0
)
[2] => Array
(
[GroupCode] => 115
[GroupDesc] => Agriculture, Forestry Support
[201308] => 234.04
[201310] => 343.02
[201309] => 0
)
)
array_fill_keys
array_walk
I have an array in php like this :
Array
(
[0] => Array
(
[915] => 1
[1295] => 1
[1090] => 1
[1315] => 0.93759357774
[128] => 0.93759357774
[88] => 0.731522789561
[1297] => 0.731522789561
[1269] => 0.525492880722
[1298] => 0.525492880722
[121] => 0.519133966069
)
[1] => Array
(
[585] => 1
[1145] => 1
[1209] => 1
[375] => 1
[1144] => 1
[913] => 1
[1130] => 0.996351158355
[215] => 0.937096401456
[1296] => 0.879373313559
[30] => 0.866473953643
[780] => 0.866473953643
[1305] => 0.866473953643
[1293] => 0.866473953643
)
)
How do I get the 1st-5th rows of sub-array for each array, like this :
Result :
Array
(
[0] => Array
(
[915] => 1
[1295] => 1
[1090] => 1
[1315] => 0.93759357774
[128] => 0.93759357774
)
[1] => Array
(
[585] => 1
[1145] => 1
[1209] => 1
[375] => 1
[1144] => 1
)
)
$multid_array = array(/* Your Multidimensional array from above*/);
$sliced_array = array(); //setup the array you want with the sliced values.
//loop though each sub array and slice off the first 5 to a new multidimensional array
foreach ($multid_array as $sub_array) {
$sliced_array[] = array_slice($sub_array, 0, 5);
}
The $sliced_array will then contain the output you wanted.
Iterate over the array.
Read the value by reference.
Delete key-values from offset 5 till
the end. You need not collect the return value because we are using the reference to the original array.
.
foreach($mainArray as $key => &$value) {
array_splice($value,5);
}
Working ideone link
You might want to look into the php function array_splice.
http://no.php.net/manual/en/function.array-slice.php