Padding data for sometimes missing object index - php

I have an array where I'm looping on an object
foreach ($product->info->details as $details) {
$skuItem[] = $details->dtl1;
$skuItem[] = $details->dtl2;
$skuItem[] = $details->dtl3;
}
The object it loops on is structured this way
"details": {
"1": {
"dtl1": "123",
"dtl2": "TEst",
"dtl3": "123"
},
"2": {
"dtl1": "12",
"dtl2": "Test",
"dtl3": "153"
}
},
The thing is, it can only have up to 2 of those sets but sometimes it has only one.
Is there a way to accomodate in my foreach loop so that if there is only one then I can basically 'dummy up' a second set with all zeroes? I'm mapping this to a file and need to make sure I'm at least always mapping all 6 values
So if the object looks like
"details": {
"1": {
"dtl1": "123",
"dtl2": "TEst",
"dtl3": "123"
}
I would want to create my array like
0 => "123",
1 => "TEst",
2 => "123"
3 => "0",
4 => "0",
5 => "0"

After the foreach, you can pad your array with zero:
foreach ($product->info->details as $details) {
$skuItem[] = $details->dtl1;
$skuItem[] = $details->dtl2;
$skuItem[] = $details->dtl3;
}
Array now contains:
0 => "123"
1 => "TEst"
2 => "123"
Now run:
$skuItem = array_pad($skuItem, 6, 0);
This will add zeros to the end of the array until you get 6 items in it, so the array now contains:
0 => '123'
1 => 'TEst'
2 => '123'
3 => 0
4 => 0
5 => 0
If you want string zero instead, then just pass that as the 3rd arg:
$skuItem = array_pad($skuItem, 6, '0');
Yields:
0 => '123'
1 => 'TEst'
2 => '123'
3 => '0'
4 => '0'
5 => '0'

You can create a template of what you want and replace with what you create in the loop:
$skuItem = array_replace(array_fill(0, 6, 0), $skuItem);
array_pad is probably better for this trivial example, but consider if you have a variety of values:
$temp = array('x', 'y', 'z', 'x', 'y', 'z');
$skuItem = array_replace($temp, $skuItem);
Or:
$temp = array('x', 'y', 'z');
if(count($skuItem) != 6) {
$skuItem = array_merge($skuItem, $temp);
}

Related

transform a two-dimensional array into a table-like structure

I have as input a 2 dimensional array. Example:
$input = [
[1,2,3],
[11, "a" => "val_a"],
[12,'b' => 'val_b', 'a' => 'val2_a'],
[2 => 22]
];
I want to convert it to an array with a tabular structure. In the table-like structure, all sub-arrays (rows) have exactly the same key in the same order. These keys are the union of all keys of the 2nd level.
New Keys: [0, 1, 2, 'a', 'b']
Elements that do not exist in the input array receive the value NULL. I expect the following result:
$expected = [
[ 0 => 1, 1 => 2, 2 => 3, 'a' => NULL, 'b' => NULL],
[ 0 => 11, 1 => NULL, 2 => NULL, 'a' => "val_a", 'b' => NULL],
[ 0 => 12, 1 => NULL, 2 => NULL, 'a' => "val2_a", 'b' => "val_b"],
[ 0 => NULL, 1 => NULL, 2 => 22, 'a' => NULL, 'b' => NULL]
];
What I've tried so far:
function rectify($array){
$maxRow = [];
foreach($array as $row){
$maxRow += $row;
}
$new = [];
foreach($array as $key => $row){
foreach($maxRow as $mKey => $mVal){
$new[$key][$mKey] = array_key_exists($mKey,$row) ? $row[$mKey] : NULL;
}
}
return $new;
}
The function delivers correct results. The solution is very complex due to 2 nested loops with one query.
Another attempt returned the same keys, but not in the same order.
This code first identifies all of the columns in the data. It then creates an empty template array (using array_unique to remove duplicates).
It then loops over the rows again and uses array_replace to fill the values in for each row...
$headers = [];
foreach ( $input as $row ) {
$headers = array_merge($headers, array_keys($row));
}
$headers = array_fill_keys(array_unique($headers), null);
$output = [];
foreach ( $input as $row ) {
$output[] = array_replace($headers, $row);
}

Cyclically mapping flat arrays of different sizes and summing the values

I have an issue with two arrays that I need to combine, where the first array contains a list of campaign names ( page_data ) like
[
"Campaign 1",
"Campaign 2",
"Campaign 3"
]
and another array that contains number of leads for the campaigns. But this array will contain twice as many keys as the campaign array like this:
[
222,
342,
71,
33,
43,
665
]
It contains twice as many keys, because it will take leads from two different forms, so the values for key 0 and key 3 will be for campaign 1 and key 2 and key 4 will be for campaign 2. It will always be this way. If there are 5 campaigns, leads array will have 10 keys and key 0 and key 5 will be for campaign one, key 1 an key 6 for campaign 2, etc.
And then I have this piece of code to combine ( push ):
foreach (json_decode($result) as $key) {
foreach ($pages["page_data"] as $p => $pvalue) {
array_push(
$leadArray,
array(
"pageName" => $pvalue["form_name"],
"pageLeads" => $key[$p]
)
);
}
}
That will incorrectly make an array that looks something like:
[
"campaign 1" => 222,
"campaign 2" => 342,
"campaign 3" => 71
]
But that will only take keys 0,1,2 and so key 3,4,5 will not be in the array.
What I want is key 0 and key 3, key 1 and key 4, etc. in the leads array to be combined so the the new leads array will be
[
255,
386,
736
]
which I can then combine with the campaigns array as the number of keys from the two arrays will now match which will give me an array that looks like
[
"campaign 1" => 255,
"campaign 2" => 386,
"campaign 3" => 736
]
Use array_chunk function for split your second array and it will be easy to sum values.
When you use this function, your array will splitted into two arrays. In first array you will have values 0, 1, 2, and in second you will have 3, 4, 5 values. Now iterate through your first array, using keys you will have access to value pairs: 0-3, 1-4, 2-5.
Check out this code:
<?php
$array1 = [0 => "Campaign 1", 1 => "Campaign 2", 2 => "Campaign 3"];
$array2 = [0 => 222, 1 => 342, 2 => 71, 3 => 33, 4 => 43, 5 => 665];
$chunkedArray2 = array_chunk($array2, count($array1), false);
$result = [];
foreach($array1 as $key => $value) {
$result[$value] = $chunkedArray2[0][$key] + $chunkedArray2[1][$key];
}
var_dump($result);
And result is:
Array
(
[Campaign 1] => 255
[Campaign 2] => 385
[Campaign 3] => 736
)
Try this one
$result = json_decode($result);
$count = count($result);
$final = array();
foreach($result as $key => $value){
$final[$value] = $pages["page_data"][$key] + $pages["page_data"][$key+$count];
}
var_dump($final);
You can avoid chunking and transposing by leveraging the modulus value between the current index and the count of the groups array.
This is optimized for efficiency (because it makes no iterated function calls), has the lowest time complexity (because it only iterates the values array once), and will work when you any number of values to process.
Code: (Demo)
$groups = ["Campaign 1", "Campaign 2", "Campaign 3"];
$values = [222, 342, 71, 33, 43, 665];
$count = count($groups);
$result = [];
foreach ($values as $index => $value) {
$group = $groups[$index % $count];
$result[$group] = ($result[$group] ?? 0) + $value;
}
var_export($result);
Output:
array (
'Campaign 1' => 255,
'Campaign 2' => 385,
'Campaign 3' => 736,
)
#aslawin approach may be realized a litle easy with some functions
$array1 = [0 => "Campaign 1", 1 => "Campaign 2", 2 => "Campaign 3"];
$array2 = [0 => 222, 1 => 342, 2 => 71, 3 => 33, 4 => 43, 5 => 665];
$res = array_combine($array1,
array_map(function($i1, $i2) { return $i1+$i2; },
...array_chunk($array2, count($array1))))
reply to comment: it's not obvious that the OP needs more than twice the length of the second array, but the code can easily be rewritten for any length
$array1 = [0 => "Campaign 1", 1 => "Campaign 2", 2 => "Campaign 3"];
$array2 = [222, 342, 71, 33, 43, 665, -255, -385, -736];
$res = array_combine($array1,
array_map(function(...$ar) { return array_sum($ar); },
...array_chunk($array2, count($array1))));
print_r($res);
output
[0, 0, 0]

Apply column min and column max to every row in a 2d array

I need to find the minimum value in one column and the maximum value in another column of a two-dimensional array and apply those values to every row in the array.
Sample input:
$array = [
["day1" => 1, "day2" => 1, "name" => "Ram"],
["day1" => 1, "day2" => 2, "name" => "Raj"],
["day1" => 1, "day2" => 3, "name" => "Rahul"],
["day1" => 2, "day2" => 3, "name" => "Rocky"]
];
In the above data set, the minimum day1 value is 1 and the maximum day2 value is 3. I need to apply those two values (respective to their column) to the day1 and day2 values in every rows.
Expected output:
[
["day1" => 1, "day2" => 3, "name" => "Ram"],
["day1" => 1, "day2" => 3, "name" => "Raj"],
["day1" => 1, "day2" => 3, "name" => "Rahul"],
["day1" => 1, "day2" => 3, "name" => "Rocky"]
]
This will help -
$data=array(array("day1"=>1,"day2"=>1,"name"=>"Ram"),array("day1"=>1,"day2"=>2,"name"=>"Raj"),array("day1"=>1,"day2"=>3,"name"=>"Rahul"),array("day1"=>2,"day2"=>3,"name"=>"Rocky"));
// Get all values for day1 & day2 and store them in one array
$values = array_merge(array_column($data, 'day2'), array_column($data, 'day1'));
// Assign values
$data = array_map(function($d) use($values) {
// Assign the minimum value
$d['day1'] = min($values);
// assign the maximum value
$d['day2'] = max($values);
return $d;
}, $data);
echo json_encode($data);
Output
[{"day1":1,"day2":3,"name":"Ram"},{"day1":1,"day2":3,"name":"Raj"},{"day1":1,"day2":3,"name":"Rahul"},{"day1":1,"day2":3,"name":"Rocky"}]
this will help: check the demo
$data=array(array("day1"=>1,"day2"=>1,"name"=>"Ram"),array("day1"=>1,"day2"=>2,"name"=>"Raj"),array("day1"=>1,"day2"=>3,"name"=>"Rahul"),array("day1"=>2,"day2"=>3,"name"=>"Rocky"));
$min = min(array_column($data, 'day1'));
$max = max(array_column($data, 'day2'));
$result = array_map(function($v) use($min, $max){$v['day1'] = $min; $v['day2'] = $max; return $v; }, $data);
Instead of using multiple cycles (foreach() loops and or array_column() calls), this task can be completed in 1 cycle by declaring reference variables at all elements which need to be updated with the min/max values.
Below, the final iteration's $day1 and $day2 values will be distributed to all points of reference.
Code: (Demo)
foreach ($array as &$row) {
$day1 = min($day1 ?? $row['day1'], $row['day1']);
$day2 = max($day2 ?? $row['day2'], $row['day2']);
$row['day1'] = &$day1;
$row['day2'] = &$day2;
}
var_export($array);

comparing two arrays in php

I use this code :
$new = array(
"123" => "a",
"456" => "b"
);
$old = array(
"123" => "a",
"456" => "b"
);
then the $new array become like this:
$new = array(
"456" => "b",
"123" => "c",
"789" => "e"
);
as you see the count of $new array increased and the order of elements changed and the value at key 123 also changed. I need to compare the $new array against the $old array and catch only the change made on the value at key 123 without caring about the order and the count of elements. I tried:
$result = array_diff( $new, $old );
print_r( $result );
output :
Array ( [123] => c [789] => e )
UPDATE. quite confusing. now I think we got it
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch this (element in old array that is changed)
"789" => "e"
);
$new2 = array();
foreach ($new as $key => $new_val)
{
if (isset($old[$key])) // belongs to old array?
{
if ($old[$key] != $new_val) // has changed?
$new2[$key] = $new[$key]; // catch it
}
}
// output $new2:
array (
123 => 'c',
)
You first of all want to have those elements of $new that are changed compared to $old (see array_diff_assoc):
$changed = array_diff_assoc($new, $old);
Of that result you want to have only those elements that have their key in $old (see array_intersect_key):
$result = array_intersect_key($changed, $old);
And that's it. You can wrap that into each other if it helps:
array_intersect_key(array_diff_assoc($new, $old), $old);
Result is:
array(1) {
[123] =>
string(1) "c"
}
Full example (Demo):
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch only the change made on the value at key 123
"789" => "e"
);
$changed = array_diff_assoc($new, $old);
$result = array_intersect_key($changed, $old);
var_dump($result);
Just a final note: There are many array functions in PHP. It's worth to go through the list and look what is fitting because most often you only need one or two of them to get things like these done.
You use this code for your requirements
<?php
function key_compare_func($key1, $key2)
{
if ($key1 == $key2)
return 0;
else if ($key1 > $key2)
return 1;
else
return -1;
}
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_intersect_ukey($array1, $array2, 'key_compare_func'));
?>

Change array keys according to another one

I have 2 arrays:
$array1 = array(1 => "aaa", 4 => "bbb", 5 => "ccc", 8 => "ddd", 9 => "eee", 11 => "fff");
$array2 = array(2 => "", 3 => "", 6 => "", 7 => "", 9 => "", 13 => "");
I want to change the keys of $array1 according to $array2. I'm given the information that an element of the second array has to correspond to another of the first one. For example I know that $array2[6] has to correspond to $array1[4].
So I should have all the keys of $array1 changed according to this rule:
$array1 = array(3 => "aaa", 6 => "bbb", 7 => "ccc", 9 => "ddd", 13 => "eee", 2 => "fff");
I don't know how to solve this. I've tried to split the first array where the element given is but I'm stuck.
You can define a function that maps and constructs a new array.
function transfer_keys($key_array,
$value_array) {
$a = array_map(null, array_keys($key_array),
$value_array);
$result = array();
foreach($a as $kv) {
$result[$kv[0]] = $kv[1];
}
return $result;
}
$array1 = array(1 => "aaa", 4 => "bbb", 5 => "ccc",
8 => "ddd", 9 => "eee", 11 => "fff");
$array2 = array(2 => "", 3 => "", 6 => "", 7 => "",
9 => "", 13 => "");
print_r(transfer_keys($array2, $array1));
if you wanna update all elements of your first array with the values in the array2 in the same order :
$i = 0;
foreach ($array1 as $v) {
while (!isset($array2[$v]))
$i++;
$array2[$i] = $v;
}
But if you want to update according to an order you pre-defined, you have to make something else, like a table defining the rule :
$assoc_array = array(
2 => 4,
3 => 7,
4 => 11,
6 => 5,
5 => 9,
8 => 1);
foreach ($assoc_array as $k => $v) {
$array1[$k] = $array2[$v];
}
Hope this helps.
Aw, you know the difference is always the same !
Then this should be something like :
function updateArray ($array1, $array2, $key_of_array1, $key_associated_of_array2) {
$diff = $key_associated_of_array2 - $key_of_array1;
foreach ($array1 as $k => $v) {
$array2[$k + $diff] = $array1[$k];
}
}
you can get first keys of both arrays using function array_keys();
suppose, $keys1 contains keys of $array1 and $keys2 cotains keys of $array2
Then move into for loop as follows:
for($i=0 ; $i<count($array1) ; $i++)
{
$result[$keys2[$i+1]] = $array1[$i];
}
print_r($result);
Hope this will be helpful to you
foreach($array1 as $item => $value)
if(isset($array2[($item + 2)]) && item != 11)
$temp[$item + 2] = $value;
elseif($item == 11)
$temp[2] = $value;
$array1 = #$temp;
Example code.. but again, you need to tell us the pattern that determines where the first array elements are being inserted into the second array elements. I think it's.. +2? Maybe?

Categories