Using array merge when array doesn't have value - php

I am wondering is it possible to merge 2 arrays that look this:
$array1 = array("a","b","c");
$array2 = array('c'=>array("blah"=>"5", "moreblah"=>"5"));
$merge = array_merge($array1,$array2);
print_r($merge);
Running this will give me this output:
Array ( [0] => a [1] => b [2] => c [c] => Array ( [blah] => 5 [moreblah] => 5 ) )
But the output I want is something similar to this:
Array( [a]=>Array([blah]=>0, [moreblah]=>0), [b]=>Array([blah]=>0, [moreblah]=>0), [c]=>Array([blah]=>5, [moreblah]=>5))
So for the first array I want the values to become the keys and then blah and moreblah to be added and set as 0 if they are not present in array 2. Also for array 2 if there is a repeat such as c in the example array 2 would just overwrite the c index and create the output I wrote above.
Is this possible? If so can I do it with a built in method or would I have to use a for loop to try get it working?
Edit:As has been pointed out to be it is not possible. Can someone explain what type of function I would need to make to be able to get the output I would want?

Something like:
EDIT: This only works when you know the keys in the second array, is this known or not? Else i change the code..
$array1 = array("a", "b", "c");
$array2 = array('c' => array("blah" => "5", "moreblah" => "5"));
$newArray = "";
foreach ($array1 as $a1) {
if (key_exists($a1, $array2)) {
//check if blah and / or moreblah is set else set the value to 0 or something else
if (key_exists("blah", $array2[$a1])) {
$blah = $array2[$a1]["blah"];
} else {
$blah = 0;
}
if (key_exists("moreblah", $array2[$a1])) {
$moreblah = $array2[$a1]["moreblah"];
} else {
$moreblah = 0;
}
$newArray[$a1] = array("blah" => $blah, "moreblah" => $moreblah);
} else {
$newArray[$a1] = array("blah" => 0, "moreblah" => 0);
}
}

$array1 = array("a", "b", "c");
$structured = array_fill_keys($array1, array('blah' => 0, 'moreblah' => 0));
Should give you the array you want as a base. Then it's a matter of looping over your data and adding them where needed.

Related

PHP - Ensure array has certain number of items

I have a PHP array which looks like this...
array
(
[0] => apple,
[1] => orange,
)
I need to ensure the array contains 4 items, so in the instance above I want to end up with this...
array
(
[0] => apple,
[1] => orange,
[2} => ,
[3] => ,
)
Am I best looping through this with a counter and creating a new array, or is there a better method?
Pad your array with elements to a size that you need:
$my_arr = [1,2];
$my_arr = array_pad($my_arr, 4, '');
This should do what you're after
$iNumberOfElements = 5;
$a = array('apple', 'orange');
if(count($a) < $iNumberOfElements){
while (count($a) < $iNumberOfElements) {
$a[] = "";
}
}
var_dump($a);
exit;
as #iainn said: php.net/manual/en/function.array-pad.php
there is this function:
$input = array(12, 10, 9);
$result = array_pad($input, 5, 0);
// result is array(12, 10, 9, 0, 0)
5 is the size of your array, 0 is the default value to empty cells

Combine Indexed arrays with the same keys

I am using the Flot jQuery plugin to create a graph on how many visitors there have been per platform. I would like to create a 4th line with total visitors, calculated by previously retrieved data.
I need to combine several multi-dimensional Indexed arrays, but not simply merging them recursively. I.E:
$arr1 = [[2016/05/04,2],[2016/05/03,4],[2016/05/02,6]];
$arr2 = [[2016/05/04,1],[2016/05/03,3],[2016/05/02,2]];
$arr3 = [[2016/05/04,6],[2016/05/03,7],[2016/05/02,8]];
The output should be:
$arrTotal = [[2016/05/04,9],[2016/05/03,14],[2016/05/02,16]];
How do I accomplish this in a (fairly) simple way?
First of all, you cannot declare your dates the way you did:
$arr1 = [[2016/05/04,2],[2016/05/03,4],[2016/05/02,6]];
Because it's going to take 2016, divide it by 5 then divide it by 4. You need to put them into quotes.
$arr1 = [['2016/05/04',2],['2016/05/03',4],['2016/05/02',6]];
But to create an associative array, you should do it this way:
$arr1 = array('2016/05/04' => 2, '2016/05/03' => 4, '2016/05/02' => 6);
$arr2 = array('2016/05/04' => 1, '2016/05/03' => 3, '2016/05/02' => 2);
$arr3 = array('2016/05/04' => 6, '2016/05/03' => 7, '2016/05/02' => 8);
Now all you want to do, is loop through each array and sum them up.
$merge = array();
function mergeArray(Array &$merge, Array $array){
// Loop through each key and value
foreach($array as $key => $value)
// Make sure the value is numeric
if(is_numeric($value)){
if(!isset($merge[$key]))
$merge[$key] = $value;
else
$merge[$key] += $value;
}
}
mergeArray($merge, $arr1);
mergeArray($merge, $arr2);
mergeArray($merge, $arr3);
And now if you dump the $merge:
array(3) {
["2016/05/04"]=>
int(9)
["2016/05/03"]=>
int(14)
["2016/05/02"]=>
int(16)
}
Build a method that will sum the values by respecting the keys of existing values.
$arr1 = array('2016/05/04'=>2,'2016/05/03'=>4,'2016/05/02'=>6);
$arr2 = array('2016/05/04'=>1,'2016/05/03'=>3,'2016/05/02'=>2);
$arr3 = array('2016/05/04'=>2,'2016/05/03'=>7,'2016/05/02'=>8);
function array_sum(&$new_arr,$arr) {
foreach ($arr as $date_key => $num_value) {
// initialize date in new array with 0, if not done previously
if (! isset($new_arr[$date_key])) { $new_arr[$date_key] = 0; }
// add number for indexed element of array
$new_arr[$date_key] += $num_value;
}
}
$new_arr = array();
array_sum($new_array,$arr1);
array_sum($new_array,$arr2);
array_sum($new_array,$arr3);
You are trying to sum up every second value from each nested array relatively to their position in the parent array.There's a short and simple solution using array_map, array_sum and array_column functions:
$groupped = array_map(null, $arr1,$arr2,$arr3);
$result = array_map(function($v){
return [$v[0][0], array_sum(array_column($v, 1))];
}, $groupped);
print_r($result);
The output:
Array
(
[0] => Array
(
[0] => 2016/05/04
[1] => 9
)
[1] => Array
(
[0] => 2016/05/03
[1] => 14
)
[2] => Array
(
[0] => 2016/05/02
[1] => 16
)
)

PHP: take out duplicate digits from an array then print them out

I'm probably [super]overthinking this. I'm trying to analyze an array with values like [1,9], [4,6] [5,5], [6,4], [9,1] and duplicate digits (I'm having a super brain fart and can't even remember the term for numbers like this) remove (the last two) so that only [1,9], [4,6] [5,5] are printed.
I was thinking that turning this array into a string and using preg_match, but I'm pretty sure this wouldn't work even if I had the correct regex.
If you have an array of pairs like this:
$x = array(
array(1,9),
array(4,6),
array(5,5),
array(6,4),
array(9,1)
);
Here is one way to get the unique pairs:
foreach ($x as $pair) {
sort($pair);
$unique_pairs[implode(',', $pair)] = $pair;
}
This uses string representations of each sorted pair as keys in a new array, so the result will have distinct values by definition.
As far as the printing them out part of your question, once you have the unique values you can loop over them and print them out in whichever format you like, for example:
foreach ($unique_pairs as $pair) { vprintf("[%d,%d]<br>", $pair); }
It looks like elements are distributed symmetrically.
We can cut the array in two halves and get only the first half with array_slice():
$array = array(
array(1,9),
array(4,6),
array(5,5),
array(6,4),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 4
[1] => 6
)
[2] => Array(
[0] => 5
[1] => 5
)
)
Demo at Codepad.
ceil() is used to round the number up to the next highest integer if there is an even number of items in the array. Example: if there is 3 items in the array, 5 / 2 will return 2.5, we want 3 items so we use ceil(2.5) which gives 3.
Example with 3 items:
$array = array(
array(1,9),
array(5,5),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 5
[1] => 5
)
)
Example with 4 items:
$array = array(
array(1,9),
array(7,7),
array(7,7),
array(9,1),
);
print_r(array_slice($array, 0, ceil(count($array) / 2)));
Result:
Array(
[0] => Array(
[0] => 1
[1] => 9
)
[1] => Array(
[0] => 7
[1] => 7
)
)
If I'm correct in understanding what you are trying to do, you want to remove the final 2 elements from the array?
There is a function in PHP called array_pop that removes the final element from the array.
$array = array_pop($array);
So if you run this twice, you will remove the final 2 elements from the array.
This is how I'd do it (and I hope I am not overthinking this :))
$stringArray = array();
$stringArray[] = '1,9';
$stringArray[] = '4,6';
$stringArray[] = '5,5';
$stringArray[] = '6,4';
$stringArray[] = '9,1';
foreach($stringArray as &$numString) {
$numString = explode(',', $numString);
usort($numString, function($a, $b) {return $a - $b;});
$numString = implode(',', $numString);
}
$a = array_unique($a);
print_r($a);
You basically explode every element into a subarray, sort it and then implode it back. After calling the array_unique, you're left with unique values in the array.
The output would be
Array
(
[0] => 1,9
[1] => 4,6
[2] => 5,5
)
The result you suggest treats [a,b] as equivalent to [b,a] which makes the problem a lot more complex. The code below gives the result you asked for, but without really understanding what the problem is that you are trying to fix and whether [1,9] is equivalent to [9,1] in the solution:
$a=array(array(1,9),array(4,6),...
$dup=array();
for ($i=0; $i<count($a) -1; $i++) {
for ($j=$i+1; $j<count($a); $j++) {
if (($a[$i][0]==$a[$j[0] && $a[$i][1]==$a[$j[1])
|| ($a[$i][0]==$a[$j[1] && $a[$i][1]==$a[$j[0])) {
$dup[]=$j;
}
}
}
foreach ($dup as $i) {
unset($a[$i]);
}
So I'm actually going to assume your question to have a different meaning than everyone else did. I believe what you're asking is:
How do you filter out array items where a reverse of the item has already been used?
<?php
// The example set you gave
$numberSets = [[1, 9], [4, 6], [5, 5], [6, 4], [9, 1]];
// Initialize an empty array to keep track of what we've seen
$keys = [];
// We use array filter to get rid of items we don't want
// (Notice that we use & on $keys, so that we can update the variable in the global scope)
$numberSets = array_filter($numberSets, function($set) use(&$keys) {
// Reverse the array
$set = array_reverse($set);
// Create a string of the items
$key = implode('', $set);
// Get the reverse of the numbers
$reversedKey = strrev($key);
// If the palindrome of our string was used, return false to filter
if (isset($keys[$reversedKey])) {
return false;
}
// Set the key so it's not used again
// Since $keys is being passed by reference it is updated in global scope
$keys[$key] = true;
// Return true to NOT filter this item, since it or it's reverse were not matched
return true;
});
var_dump($numberSets);

Putting an array (at the end OR beginning) subarray of another array

Say I got this array:
array([0] => 0 [1] => 0 [2] => 1), how can I put this as the value of the nth key of another array, making
$array = array(
[0] => array([0] => 0 [1] => 0 [2] => 1)
)
in this example it is the 0th key of array $array
I had browsed with PHP array functions, but I got tired looking for a function that does the same thing
EDIT.
Doing: $array[0] = array(0, 0, 1); works great for first loop, but if I would like to add another array as subarray, say array(1, 1, 1), my output should be
$array = array(
[0] => array([0] => 0 [1] => 0 [2] => 1 [3] => 1 [4] => 1 [5] => 1)
)
Note that the new array, was added at the end of the last subarray.
Please help! thanks!
EDIT
$x=0;
while($x<count($WOE_CONTROL)) {
$j=0;
while($j<=30) {
if ($WOE_CONTROL[$x+3]&(1<<$j)) {
echo '<br />';
echo '<strong>'.$Castles[$j].'</strong>';
$castle_data_holder[0] = $WOE_CONTROL[$x];
$castle_data_holder[1] = $WOE_CONTROL[$x+1];
$castle_data_holder[2] = $WOE_CONTROL[$x+2];
$castle_db[$j] = $castle_data_holder;
unset ($castle_data_holder);
}
if ($x+4 < count($WOE_CONTROL)) {echo " ";}
$j=$j+1;
}
$x=$x+4;
}
Sorry, there, I am trying to extract all the data in $WOE_CONTROL which actually contains binary data, then store them temporarily to $castle_data_holder then finally, add it to $castle_db
Just set the value of $array[0] to the array. This produces a multidimensional array.
$array[0] = array(0, 0, 1);
Is this u looking for?
$array[] = array(0,0,1);
$array[] = array(1,1,1);
$array[] = array(2,2,2);
// etc...
print_r($array);
EDIT
$array[]['a1'] = array(1,1,1);
$array[]['a2'] = array(2,2,2);
$array[]['a3'] = array(3,3,3);
// etc...
print_r($array);
Finally this is u need
$a = array(1,1,1);
$b = array(2,2,2);
$c = array(3,3,3);
$value = array_merge($a,$b,$c);
print_r($value);
EDIT
$newArray = array();
foreach($yourArray as $key => $value)
{
// I say if $value is an array that u want to merge
$arrayToMerge = $value;
$newArray = array_merge($newArray,$arrayToMerge);
}
print_r($newArray);
This solved my problem:
if (empty($castle_db[$j])) {
$castle_db[$j] = $castle_data_holder;
}
else {
$castle_db[$j] = array_merge($castle_db[$j],$castle_data_holder);
}
it is going to check if the array is empty if not use merge.
Thanks everyone!

Associative Array for places

I have 2 arrays that I have made into an Associative Array. I also have combinations of winner positions = ie '1,2', '2,3', '1,3'. What I need to do is replace the position numbers with jersey numbers and put back into the same configuration as the combinations were written. For Example, I've set up my jersey, position, combo, and associative array:
$jersey = array('3','1','5','4');
$position = array('1','2','3','4');
$AssocArr = array_combine($position, $jersey);
$Combo = array('1,2','2,3','1,3');
I've set up a function to get the values from the keys:
function getVals($finishPosMap, $keys) {
foreach($keys as $key) {
$output[] = $finishPosMap[$key];
}
return $output;
}
The part I'm having issue with is putting them back into an array with the values instead of keys. This is what I've done so far:
foreach($Combo as $set=>$pCombo) {
$com = array($set=>(explode(',', $pCombo)));
foreach($com as $set=>$com){
$c = getVals($AssocArr, $com);
print_r($c);
}
}
print_r gives me:
array( [0] => 3 [1] => 1 )
array( [0] => 1 [1] => 5 )
array( [0] => 3 [1] => 5 )
Can anyone help me put it in the format:
array(0 => '3,1', 1 => '1,5', 2 => '3,5');
Thanks in advance for your help, and please let me know if you think there'd be a better way to do this. Thanks!
I think what you're missing is the array_intersect_key(); this should do it:
$jersey = array('3','1','5','4');
$position = array('1','2','3','4');
$AssocArr = array_combine($position, $jersey);
$Combo = array('1,2','2,3','1,3');
foreach ($Combo as &$value) {
$values = explode(',', $value, 2);
$new_values = array_intersect_key($AssocArr, array_flip($values));
$value = join(',', $new_values);
}
print_r($Combo);
It updates the $Combo array in-place and for each value, calculates the intersection with your associate array.
Demo

Categories