how to unset all multidimensional arrays with some exception keys - php

i have an array like this
Array
(
[zero] => 0
[one] => 1
[two] => 2
[three] => 3
)
I made several keys for exceptions that would be unset (zero and two).
I also got this code in another sources but it doesn't apply if I add a symbol !
$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array('zero','two');
$r = array_diff_key($r, array_flip($dontRemove));
result is
Array
(
[one] => 1
[three] => 3
)
result i want is to unset keys one and three, like this
Array
(
[zero] => 0
[two] => 2
)

$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array($r['zero'],$r['two']);
$r = array_intersect($r, $dontRemove);
print_r($r);
Array
(
[zero] => 0
[two] => 2
)
I think you can solve it from here?

Another option is array_filter:
$r = ["zero" => 0, "one" => 1, "two" => 2, "three" => 3];
$dontRemove = array('zero','two');
print_r(array_filter(
$r,
function($k) use ($dontRemove) { return in_array($k, $dontRemove); },
ARRAY_FILTER_USE_KEY
));

yet another option, not using function(s) - $result contains the desired outcome:
$filter = ['zero', 'two'];
foreach($array as $akey => $aval) {
foreach($filter as $fkey => $fval) {
if($akey === $fval) $result[$akey] = $aval;
}
}

Related

Sum like values in Multi-Dimensional array php

I need to sum the values in element 1 of my array where the values in element 0 are duplicate.
Here's a small piece of my array
Array
(
[0] => 3
[1] => 1
)
Array
(
[0] => 3
[1] => 2
)
Array
(
[0] => 3
[1] => 128
)
Array
(
[0] => 39
[1] => 4
)
The results i'm expecting to see
Array
(
[0] => 3
[1] => 131
)
Array
(
[0] => 39
[1] => 4
)
I'm still really new to PHP so any help is greatly appreciated.
You can use a combination of array_intersect, array_column and array_sum to only iterate twice. (One for each unique column 0 value).
$col0 = array_column($arr, 0);
$col1 = array_column($arr, 1);
Foreach(array_unique($col0) as $val){
$res[] = [$val, array_sum(array_intersect_key($col1, array_intersect($col0,[$val])))];
}
Var_dump($res);
https://3v4l.org/gKb5b
The way I've done it is made sure all duplicates where put in the same array.
// Your data
$sample = [[3, 1],[3, 2],[3, 128],[39, 4]];
foreach($sample as $array){
$tmp[$array[0]][] = $array[1];
}
# Output: {"3":[1,2,128],"39":[4]}
Now sum the arrays, and put it back to the structure it originally was.
foreach($tmp as $k => $v){
$new[] = [$k, array_sum($v)];
}
# Output: [[3,131],[39,4]]
But many roads lead to Rome.
Try this code. It may help you.
$array = array(["0" => 3, "1" => 1] , ["0" => 3, "1" => 2], ["0" => 3, "1" => 128], ["0" => 39, "1" => 4]);
$finalArray = [];
foreach($array as $a) {
$finalArray[$a[0]][0] = $a[0];
$finalArray[$a[0]][1] = !isset($finalArray[$a[0]][1]) ? $a[1] : $finalArray[$a[0]][1] + $a[1];
}
echo '<pre>';
print_r($finalArray);
exit;
You could do something like this. I have separated into two foreach. Hope it helps.
<?php
$a = [[3,1],[3,2],[3,128],[39,4]];
$result=[];
$temp = [];
foreach($a as $line) {
$temp[$line[0]] += $line[1];
}
foreach($temp as $k => $value) {
$result[]=[$k ,$value];
}
$data =
[
[3,1],
[3,2],
[3,128],
[39,4]
];
foreach($data as $item)
$sums[$item[0]] = ($sums[$item[0]] ?? 0) + $item[1];
$result = array_map(null, array_keys($sums), $sums);
var_export($result);
Output:
array (
0 =>
array (
0 => 3,
1 => 131,
),
1 =>
array (
0 => 39,
1 => 4,
),
)
$arr = [ [ 3, 1],[ 3, 2 ],[ 3, 128], [ 39, 4]];
$sum = [];
foreach($arr as $value) {
$sum[$value[0]][] = $value[1];
}
foreach($sum as $key=>$value ) {
$result[] = [ $key, array_sum($value)];
}
Output:
Array
(
[0] => Array
(
[0] => 3
[1] => 131
)
[1] => Array
(
[0] => 39
[1] => 4
)
)

Create a 'results' array based on comparison of two two-dimensional arrays?

I have two two-dimensional arrays I'd liked to compare to one another:
$array1
Array
(
[0] => Array
(
[A] => GB
[B] => Harry
[C] => British Army
[D] => Eton College
[E] => Cressida Bonas
)
[1] => Array
(
[A] => GB
[B] => William
[C] => Royal Air Force
[D] => Eton College
[E] => Catherine Middleton
)
)
$array2
Array
(
[0] => Array
(
[A] => GB
[B] => Harry
[C] => British Army
[D] => Eton College
[E] => Cressida Bonas
)
[1] => Array
(
[A] => GB
[B] => James
[C] => British Army
[D] => Millfield
[E] => Unknown
)
)
And produce a boolean true/false results array as follows if any of the child array values differ:
$results_array
Array
(
[0] => Array
(
[0] => true
)
[1] => Array
(
[0] => false
)
)
UPDATE:
Both arrays will always have the same length parent arrays (but the child arrays values may vary in length).
I can't wrap my head around how to use foreach in a recursive manner to get the results array.
Any general ideas or advice?
You could do using == operator. Passing the first array as key-array ($k=>$arr) [since the value is another array]. Now compare the two arrays using the simple == comparison operator. You can even perform strict matching using the === operator.
<?php
$arr1=array(0=>array('A'=>'GB','B'=>'Harry','C'=>'British Army'),1=>array('A'=>'GB','B'=>'William','C'=>'Royal Air Force'));
$arr2=array(0=>array('A'=>'GB','B'=>'Harry','C'=>'British Army'),1=>array('A'=>'GB','B'=>'James','C'=>'British Army'));
foreach($arr1 as $k=>$arr)
{
$resarr[][$k]=($arr==$arr2[$k])? "true" : "false";
}
print_r($resarr);
Demo
OUTPUT :
Array
(
[0] => Array
(
[0] => true
)
[1] => Array
(
[1] => false
)
)
I don't know what you are trying to do with a foreach loop. Are you saying every array will have 2 child arrays or every child array will have 5 values? Regardless, I hope this helps you!
I would use some of these:
array_intersect
array_intersect_assoc
array_diff
array_diff_assoc
Code:
<?php
$array1 = [
[
'A' => 'GB',
'B' => 'Harry',
'C' => 'British Army',
'D' => 'Eton College',
'E' => 'Cressida Bonas',
],
[
'A' => 'GB',
'B' => 'William',
'C' => 'Royal Air Force',
'D' => 'Eton College',
'E' => 'Catherine Middleton',
]
];
// What Values are in common
$result1 = array_intersect_assoc($array1[0], $array1[1]);
print_r($result1);
$array2 = [
[
'A' => 'GB',
'B' => 'Harry',
'C' => 'British Army',
'D' => 'Eton College',
'E' => 'Cressida Bonas',
],
[
'A' => 'GB',
'B' => 'James',
'C' => 'British Army',
'D' => 'Millfield',
'E' => 'Unknown',
]
];
// What values are different
$result2 = array_diff_assoc($array2[0], $array2[1]);
print_r($result2);
// A Way to check numerically
$perfectMatch = 5;
$intersect = array_intersect_assoc($array1[0], $array1[1]);
$intersectCount = count($intersect);
if ($intersectCount != $perfectMatch) {
echo "<br> Not Every value matches.";
} else {
echo "<br> Perfect Match!";
}
To compare the full arrays $array1 and $array2 you can do:
<?php
// (With array code above)
$c1 = count($array1);
$c2 = count($array2);
if ($c1 != $c2) {
echo "<br>Array Children must be the same";
}
$result = [];
for ($i = 0; $i < $c1; $i++) {
$in_common = array_intersect($array1[$i], $array2[$i]);
$result[] = count($intersect);
}
print_r($result);
You can just use array_map(), assuming both arrays are of the same length:
$result = array_map(function($a, $b) {
return [$a == $b]; // create single element boolean array
}, $array1, $array2);
You can use either == or ===; the former (==) will yield true if both arrays have the same key and value pairs, whereas the latter (===) will only yield true if the keys of both arrays are also in the same order.
Some answers use the == operator; however that will not work if the arrays do not have the same key=>value matchings; Try this:
$results = array();
foreach ($array1 as $i => $subarray)
{
/* No need to proceed if subarray[i] does not exist in the second array */
if(!is_array($array2[$i]))
{
$results[$i] = false;
continue;
}
$results[$i] = (count(array_diff($array1[$i], $array2[$i])) == 0) ? true : false;
}
This solution is a bit slower than using the == comparison operator. However using the == will not work for a case like:
$array1 => array(1 => "John", 2 => "James");
$array2 => array(1 => "James", 2 => "John");
Here, the keys are not the same, but the values are duplicated. Solutions using == will return false when comparing these arrays.
$array1 == $array2 // False

Adding arrays in php

Arrays have been comprehensively covered but am still stumped about how to go around this. I have two arrays which i want to merge without overwriting duplicate keys i.e.
Array1
(
[0] => 0
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 0
[6] => 0
)
+
Array2
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
[5] => 0
[6] => 1
)
my ideal result is
Array1 + Array2
(
[0] => 0
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 0
[6] => 1
)
How would i do this? I've tried using + but it gives the first array as the result
What you want to do is to map both arrays into single array, containing max value from two respective values, like that:
$array1 = array(0, 1, 1, 1, 1, 0, 0);
$array2 = array(0, 0, 0, 0, 0, 0, 1);
$result = array_map('max', $array1, $array2);
See the result here: http://ideone.com/clone/MN568
It looks like that:
array(7) {
[0]=>
int(0)
[1]=>
int(1)
[2]=>
int(1)
[3]=>
int(1)
[4]=>
int(1)
[5]=>
int(0)
[6]=>
int(1)
}
array_merge() does not overwrite duplicate elements that have numeric keys.
Given the arrays are of the same length:
function bitwise_or_arrays($arr1, $arr2) {
$result = array();
for ($i = 0; $i < count($arr1); $i++) {
$result[$i] = $arr1 | $arr2;
}
return $result;
}
If you are looking for the greater (nonzero) of the two arrays, you can iterate like so:
$array1 = array(1,0,0,1,1,1);
$array2 = array(0,0,1,0,0,1);
$newarr = array();
foreach ($array1 as $k => $v) {
$newarr[$k] = max($array1[$k], $array2[$k]);
}
print_r($newarr);
Array
(
[0] => 1
[1] => 0
[2] => 1
[3] => 1
[4] => 1
[5] => 1
)
If what you need is to add the values, use:
$newarr = array();
foreach ($array1 as $k => $v) {
$newarr[$k] = $array1[$k] + $array2[$k];
}
Just for fun (although in your case with 0 and 1 values it works :)
$array1 = array(0, 1, 1, 1, 1, 0, 0);
$array2 = array(0, 0, 0, 0, 0, 0, 1);
$str1 = implode('', $array1);
$str2 = implode('', $array2);
$result = str_split($str1 | $str2);
Sorry for this variant, I know it's crazy, but just couldn't not to post it. Arrays look like bit masks 0111100 and 0000001. So just using bitwise | operator.
So result:
Array
(
[0] => 0
[1] => 1
[2] => 1
[3] => 1
[4] => 1
[5] => 0
[6] => 1
)
If what your looking is to combine them use array_combine().
$a = array('green', 'red', 'yellow');
$b = array('avocado', 'apple', 'banana');
$c = array_combine($a, $b);
print_r($c);
//*output:
array(
[green] => avocado
[red] => apple
[yellow] => banana
)
here's how to merge array:
$beginning = 'foo';
$end = array(1 => 'bar');
$result = array_merge((array)$beginning, (array)$end);
print_r($result);
//output:
Array(
[0] => foo
[1] => bar
)
heres how to add values
$a = array(0=>1, 1=>2, 2=>3, 3=>4);
$b = array(0=>5, 1=>6, 2=>7, 3=>8);
$c = $a[0] += $b[0];
print_r($c);//output: 6
im not a guru on php but i hope this helps you even just abit.
Just for the fun of it:
$array1 = array(0,1,1,1,1,0,0);
$array2 = array(0,0,0,0,0,0,1);
$array3 = str_split(decbin(bindec(implode('',$array1)) | bindec(implode('',$array2))));
var_dump($array3);
Unfortunately it trims leading zeroes
Using
$array3 = str_split(str_pad(decbin(bindec(implode('',$array1)) | bindec(implode('',$array2))),count($array1),'0',STR_PAD_LEFT));
will restore leading zeroes, but doesn't feel as clean

How do I use array_unique on an array of arrays?

I have an array
Array(
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[1] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[2] => Array
(
[0] => 33
[user_id] => 33
[1] => 8
[frame_id] => 8
)
[3] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[4] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
As you can see key 0 is the same as 1, 3 and 4. And key 2 is different from them all.
When running the array_unique function on them, the only left is
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Any ideas why array_unique isn't working as expected?
It's because array_unique compares items using a string comparison. From the docs:
Note: Two elements are considered
equal if and only if (string) $elem1
=== (string) $elem2. In words: when the string representation is the same.
The first element will be used.
The string representation of an array is simply the word Array, no matter what its contents are.
You can do what you want to do by using the following:
$arr = array(
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 8)
);
$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'user' => int 3
2 =>
array
'user_id' => int 33
'user' => int 8
Here's how it works:
Each array item is serialized. This
will be unique based on the array's
contents.
The results of this are run through array_unique,
so only arrays with unique
signatures are left.
array_intersect_key will take
the keys of the unique items from
the map/unique function (since the source array's keys are preserved) and pull
them out of your original source
array.
Here's an improved version of #ryeguy's answer:
<?php
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 5)
);
# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
return $el['user_id'];
}, $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'tmp_id' => int 3
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
The trick here is that array_unique() preserves the keys:
$ php -r 'var_dump(array_unique([1, 2, 2, 3]));'
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[3]=>
int(3)
}
This let's array_intersect_key() leave the desired elements.
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize didn't work, since the attrs were different, namely, photo_reference and reference. Probably these are like temporary ids.
array_unique() only supports multi-dimensional arrays in PHP 5.2.9 and higher.
Instead, you can create a hash of the array and check it for unique-ness.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
array_unique deosn't work recursive, so it just thinks "this are all Arrays, let's kill all but one... here we go!"
Quick Answer (TL;DR)
Distinct values may be extracted from PHP Array of AssociativeArrays using foreach
This is a simplistic approach
Detailed Answer
Context
PHP 5.3
PHP Array of AssociativeArrays (tabluar composite data variable)
Alternate name for this composite variable is ArrayOfDictionary (AOD)
Problem
Scenario: DeveloperMarsher has a PHP tabular composite variable
DeveloperMarsher wishes to extract distinct values on a specific name-value pair
In the example below, DeveloperMarsher wishes to get rows for each distinct fname name-value pair
Solution
example01 ;; DeveloperMarsher starts with a tabluar data variable that looks like this
$aodtable = json_decode('[
{
"fname": "homer"
,"lname": "simpson"
},
{
"fname": "homer"
,"lname": "jackson"
},
{
"fname": "homer"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "johnson"
},
{
"fname": "bart"
,"lname": "jackson"
},
{
"fname": "bart"
,"lname": "simpson"
},
{
"fname": "fred"
,"lname": "flintstone"
}
]',true);
example01 ;; DeveloperMarsher can extract distinct values with a foreach loop that tracks seen values
$sgfield = 'fname';
$bgnocase = true;
//
$targfield = $sgfield;
$ddseen = Array();
$vout = Array();
foreach ($aodtable as $datarow) {
if( (boolean) $bgnocase == true ){ #$datarow[$targfield] = #strtolower($datarow[$targfield]); }
if( (string) #$ddseen[ $datarow[$targfield] ] == '' ){
$rowout = array_intersect_key($datarow, array_flip(array_keys($datarow)));
$ddseen[ $datarow[$targfield] ] = $datarow[$targfield];
$vout[] = Array( $rowout );
}
}
//;;
print var_export( $vout, true );
Output result
array (
0 =>
array (
0 =>
array (
'fname' => 'homer',
'lname' => 'simpson',
),
),
1 =>
array (
0 =>
array (
'fname' => 'bart',
'lname' => 'johnson',
),
),
2 =>
array (
0 =>
array (
'fname' => 'fred',
'lname' => 'flintstone',
),
),
)
Pitfalls
This solution does not aggregate on fields that are not part of the DISTINCT operation
Arbitrary name-value pairs are returned from arbitrarily chosen distinct rows
Arbitrary sort order of output
Arbitrary handling of letter-case (is capital A distinct from lower-case a ?)
See also
php array_intersect_key
php array_flip
function array_unique_recursive($array)
{
$array = array_unique($array, SORT_REGULAR);
foreach ($array as $key => $elem) {
if (is_array($elem)) {
$array[$key] = array_unique_recursive($elem);
}
}
return $array;
}
Doesn't that do the trick ?
`
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
);
$arr1 = array_unique($arr,SORT_REGULAR);
echo "<pre>";
print_r($arr1);
echo "</pre>";
Array(
[0] => Array(
[user_id] => 33
[tmp_id] => 3
)
[1] => Array(
[user_id] => 33
[tmp_id] => 4
)
)
`

How can I merge PHP arrays?

I have two arrays of animals (for example).
$array = array(
array(
'id' => 1,
'name' => 'Cat',
),
array(
'id' => 2,
'name' => 'Mouse',
)
);
$array2 = array(
array(
'id' => 2,
'age' => 321,
),
array(
'id' => 1,
'age' => 123,
)
);
How can I merge the two arrays into one by the ID?
#Andy
http://se.php.net/array_merge
That was my first thought but it doesn't quite work - however array_merge_recursive might work - too lazy to check right now.
This does what Erik suggested (id no. as array key) and merges vlaues in $array2 to $results.
$results = array();
foreach($array as $subarray)
{
$results[$subarray['id']] = array('name' => $subarray['name']);
}
foreach($array2 as $subarray)
{
if(array_key_exists($subarray['id'], $results))
{
// Loop through $subarray would go here if you have extra
$results[$subarray['id']]['age'] = $subarray['age'];
}
}
First off, why don't you use the ID as the index (or key, in the mapping-style array that php arrays are imo)?
$array = array(
1 => array(
'name' => 'Cat',
),
2 => array(
'name' => 'Mouse',
)
);
after that you'll have to foreach through one array, performing array_merge on the items of the other:
foreach($array2 as $key=>$value) {
if(!is_array($array[$key])) $array[$key] = $value;
else $array[$key] = array_merge($array[key], $value);
}
Something like that at least. Perhaps there's a better solution?
<?php
$a = array('a' => '1', 'b' => array('t' => '4', 'g' => array('e' => '8')));
$b = array('c' => '3', 'b' => array('0' => '4', 'g' => array('h' => '5', 'v' => '9')));
$c = array_merge_recursive($a, $b);
print_r($c);
?>
array_merge_recursive — Merge two or more arrays recursively
outputs:
Array
(
[a] => 1
[b] => Array
(
[t] => 4
[g] => Array
(
[e] => 8
[h] => 5
[v] => 9
)
[0] => 4
)
[c] => 3
)
#Andy
I've already looked at that and didn't see how it can help merge multidimensional arrays. Maybe you could give an example.
#kevin
That is probably what I will need to do as I think the code below will be very slow.
The actual code is a bit different because I'm using ADOdb (and ODBC for the other query) but I'll make it work and post my own answer.
This works, however I think it will be very slow as it goes through the second loop every time:
foreach($array as &$animal)
{
foreach($array2 as $animal2)
{
if($animal['id'] === $animal2['id'])
{
$animal = array_merge($animal, $animal2);
break;
}
}
}
foreach ($array as $a)
$new_array[$a['id']]['name'] = $a['name'];
foreach ($array2 as $a)
$new_array[$a['id']]['age'] = $a['age'];
and this is result:
[1] => Array
(
[name] => Cat
[age] => 123
)
[2] => Array
(
[name] => Mouse
[age] => 321
)
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
With PHP 5.3 you can do this sort of merge with array_replace_recursive()
http://www.php.net/manual/en/function.array-replace-recursive.php
You're resultant array should look like:
Array (
[0] => Array
(
[id] => 2
[name] => Cat
[age] => 321
)
[1] => Array
(
[id] => 1
[name] => Mouse
[age] => 123
)
)
Which is what I think you wanted as a result.
I would rather prefer array_splice over array_merge because of its performance issues, my solution would be:
<?php
array_splice($array1,count($array1),0,$array2);
?>
$new = array();
foreach ($array as $arr) {
$match = false;
foreach ($array2 as $arr2) {
if ($arr['id'] == $arr2['id']) {
$match = true;
$new[] = array_merge($arr, $arr2);
break;
}
}
if ( !$match ) $new[] = $arr;
}

Categories