How to split multidimensional array into multiple array dynamically - php

I got multidimensional arrays i want it to break into multi array in one variable
Array
(
[name] => Array
(
[0] => John Davis
[1] => Marie J
)
[work] => Array
(
[0] => employee
[1] => none
)
[address] => Array
(
[0] => street 1
[1] => street 2
)
)
I want output to :
$array1 = array("name" => "John Davis", "work" => "employee", "address" => "street 1");
$array2 = array("name" => "Marie J", "work" => "none", "address" => "street 2");
and how to generate dynamically if values keys more than 2
thanks alot

Please try below code get output:
$newArray = [];
foreach ($outerArray as $outerkey => $outerArr) {
foreach ($outerArr as $key => $innerArr) {
$newArray[$key][$outerkey] = $innerArr;
}
}
print_r($newArray);

Functional solution
// make array of keys
$keys = array_keys($arr);
// combine it with data sets
$res = array_map(function (...$x) use($keys)
{ return array_combine($keys, $x); },
...array_values($arr));
demo

Related

Remove subsets from each row where the same subset is found in another row

I need to remove objects from a 3d array where the same two-property object is found in any other row.
I previously asked this similar question, but my new requirements are slightly different because I was keeping one of the encountered duplicates. Now I would like for both/all encountered duplicates to be removed.
[
[
["name" => "John", "surname" => "Smith"],
["name" => "Kate", "surname" => "Winston"]
],
[
["name" => "Kate", "surname" => "Winston"],
["name" => "Jack", "surname" => "Irving"]
],
]
Desired filtered result with same original structure:
[
[
["name" => "John", "surname" => "Smith"],
],
[
["name" => "Jack", "surname" => "Irving"]
],
]
Seems like others answers don't see their own final results and don't read desired output.
Here a little bit hard solution but it works well.
Note: the input data array must have 2 object indexes and 2 arrays of objects for comparing, otherwise, it should be fixed.
$ar = Array (
0 => [(object)["name"=>"John", "surname"=>"Smith"], (object)["name"=>"Kate", "surname"=>"Winston"]],
1 => [(object)["name"=>"Kate", "surname"=>"Winston"], (object)["name"=>"Jack", "surname"=>"Irving"]]
);
$arr = [];
$k = 0; // do `if statement` only once
foreach($ar as $num=>&$subar){
foreach($subar as $num2=>$pers){
$subar[$num2] = (array)$pers; // object to array
if (!$k) {
$keys = array_keys($subar[$num2]); // collect "name" and "surname" in an array
$k++;
}
foreach($subar[$num2] as $a=>$b){
$seq = array_search($a,$keys); // index of the current key
if (!$seq) { // 0 -> "name", 1 -> "surname"
$arr[$num][$b] = '';
} else {
$arr[$num][$subar[$num2][current($keys)]] = $b;
}
}
}
}
$diff[] = array_diff($arr[0],$arr[1]); // clear duplicates from 1-st set
$diff[] = array_diff($arr[1],$arr[0]); // clear duplicates from 2-nd set
Gives result:
Array
(
[0] => Array
(
[John] => Smith
)
[1] => Array
(
[Jack] => Irving
)
)
And after you can re-create the output array:
// creating a new array
$res = [];
foreach($diff as $num=>$ns){
foreach($ns as $name=>$surname){
foreach($keys as $ind=>$key){
if ($ind % 2 == 0){
$tmp[$key] = $name; // put name
} else {
$tmp[$key] = $surname; // put surname
}
}
$res[$num] = (object)$tmp; // array to object
}
}
Output will be:
Array
(
[0] => stdClass Object
(
[name] => John
[surname] => Smith
)
[1] => stdClass Object
(
[name] => Jack
[surname] => Irving
)
)
Demo
In case of string values in the input arrays, i.e.:
$ar = [
'[{"name":"John", "surname":"Smith"}, {"name":"Kate", "surname":"Winston"}]',
'[{"name":"Kate", "surname":"Winston"}, {"name":"Jack", "surname":"Irving"}]'
];
You need a little fix:
...
foreach($ar as $num=>&$subar){
$ar[$num] = json_decode($subar);
foreach($subar as $num2=>$pers){
...
The same output you will get.
Demo
It's easier if you don't trim away the brackets [], as you stated that you did in the comments. That way, they are proper JSON strings, which we can use in PHP.
Map (or loop) over your array, and build up a $result array, where you append all the arrays from your decoded JSON. Once you have your final $result, you have an array that looks somewhat like
Array (
[0] => Array
(
[name] => John
[surname] => Smith
)
[1] => Array
(
[name] => Kate
[surname] => Winston
)
[2] => Array
(
[name] => Kate
[surname] => Winston
)
[3] => Array
(
[name] => Jack
[surname] => Irving
)
)
We have all the values in an actual array now, but there are duplicates -- which can be removed using array_unique() with the SORT_REGULAR flag.
$array = [
'[{"name":"John", "surname":"Smith"}, {"name":"Kate", "surname":"Winston"}]',
'[{"name":"Kate", "surname":"Winston"}, {"name":"Jack", "surname":"Irving"}]'
];
$result = [];
array_map(function($v) use (&$result) {
$result = array_merge($result, json_decode($v, true));
}, $array);
print_r(array_unique($result, SORT_REGULAR));
Final output:
Array
(
[0] => Array
(
[name] => John
[surname] => Smith
)
[1] => Array
(
[name] => Kate
[surname] => Winston
)
[3] => Array
(
[name] => Jack
[surname] => Irving
)
)
Live demo at https://3v4l.org/q6pZc
$array = [
'[{"name":"John", "surname":"Smith"}, {"name":"Kate", "surname":"Winston"}]',
'[{"name":"Kate", "surname":"Winston"}, {"name":"Jack", "surname":"Irving"}]'
];
$resultArray = [];
foreach ($array as $item) {
$bufferArray = array_merge($resultArray, json_decode($item));
foreach ($bufferArray as $elements) {
$key = $elements->name . $elements->surname;
if (array_key_exists($key, $resultArray)) {
unset($resultArray[$key]);
} else {
$resultArray[$key] = $elements;
}
}
}
print_r($resultArray);
Output
Array
(
[KateWinston] => stdClass Object
(
[name] => Kate
[surname] => Winston
)
[JackIrving] => stdClass Object
(
[name] => Jack
[surname] => Irving
)
)
can rewrite this into more serious code )
To remove objects from each row where a given object exists any where in any other row, you can make iterates calls of array_udiff(). Inside the function, the first parameter should be the currently iterated row and the next/subsequent parameter(s) should all of the other rows in the entire array. The last parameter is the callback which compares whole objects to whole objects via PHP's performance-optimized algorithm.
My snippet below will not only handle your 2-row array, it will also handle arrays with 3 or more rows.
Code: (Demo)
$result = [];
foreach ($array as $i => $objs) {
$cache = $array[$i];
unset($array[$i]);
$params = [
$objs,
...$array,
fn($a, $b) => $a <=> $b
];
$result[] = array_udiff(...$params);
$array[$i] = $cache;
}
var_export($result);
To be clear, this snippet will work the same if the array of arrays of objects is an array of arrays of arrays.

PHP Find same values in TWO multidimensional arrays and map them in separate array

I have two multidimensional arrays:
Array (
[1] => Array
(
[id] => 1
[email] => aaa#mail.com
some irrelevant pairs
)
[2] => Array
(
[id] => 2
[email] => bbb#mail.com
some irrelevant pairs
)
[3] => Array
(
[id] => 3
[email] => ccc#mail.com
some irrelevant pairs
))
Array (
[1] => Array
(
[id] => 4
[email] => aaa#mail.com
some irrelevant pairs
)
[2] => Array
(
[id] => 5
[email] => bbb#mail.com
some irrelevant pairs
)
[3] => Array
(
[id] => 6
[email] => ccc#mail.com
some irrelevant pairs
))
As you see they both have key 'email' with the same values. How to extract the pairs of IDs as key-value pairs in the separate array as a map of the same emails ? I tried with foreach loops and in_array function, but something was wrong. This is what I need:
Result (pairs of IDs where e-mail values are the same:
my_array_with_pairs_of_IDs = ( "1" => "4", "2" => "5", "3" => "6" );
Please help, Thanks a lot!
Performance optimized, based on #Andreas answer:
$map1 = array_column($arr1, 'id', 'email');
$map2 = array_column($arr2, 'id', 'email');
$result = [];
foreach ($map1 as $email => $id)
{
if (isset($map2[$email]))
{
$result[$id] = $map2[$email];
}
}
removed $arr1 and $arr2 overriding;
added $result declaration.
You can use array_column to make two flat arrays that you can use array_search in.
If array_search returns not false, it's the key of the found match.
$arr1 = array_column($arr1, 'email', 'id');
$arr2 = array_column($arr2, 'email', 'id');
foreach($arr1 as $key => $val){
$find = array_search($val, $arr2);
if($find !==false) $result[$key] = $find;
}
var_dump($result);
Output:
array(3) {
["1 "]=>
string(2) "4 "
["2 "]=>
string(2) "5 "
["3 "]=>
string(2) "6 "
}
https://3v4l.org/6XhUd
You can use this method and store data in new array
$result = [];
foreach($a1 as $a){
foreach($b1 as $b){
if($b[email] == $a[email])
$result[] = [$a[id]=>$b[id]];
}
}

PHP merge associative arrays with duplicate keys

I have an array like this:
$array1 = [
['State'=>'Utah', 'users'=>5],
['State'=>'California', 'users'=>10]
]
$array2 = [
['State'=>'Utah', 'emails'=>18],
['State'=>'Arizona', 'emails'=>32],
['State'=>'California', 'emails'=>28],
]
How would I merge them so that it will become like this:
$mergedArray = [
['State'=>'Utah', 'users'=>5, 'emails'=>18],
['State'=>'Arizona', 'emails'=>32],
['State'=>'California', 'users'=>10, 'emails'=>28]
]
I tried array_merge but it only kept data from the first array.
Edit: Notice how the length and order of the array can be different.
Use array_replace_recursive function:
$array1 = ['Utah'=>['users'=>5],'California'=>['users'=>10]];
$array2 = ['Utah'=>['emails'=>18],'California'=>['emails'=>28]];
$result = array_replace_recursive($array1, $array2);
print_r($result);
The output:
Array
(
[Utah] => Array
(
[users] => 5
[emails] => 18
)
[California] => Array
(
[users] => 10
[emails] => 28
)
)
Update:
Though you have changed your initial requirements I also have solution for your new input data.Used functions: array_merge and array_values
// user data
$array1 = [
['State'=>'Utah', 'users'=>5],
['State'=>'California', 'users'=>10]
];
// email data
$array2 = [
['State'=>'Utah', 'emails'=>18],
['State'=>'Arizona', 'emails'=>32],
['State'=>'California', 'emails'=>28],
];
$result = [];
foreach (array_merge($array1, $array2) as $item) {
if (isset($result[$item['State']])) {
$result[$item['State']] = array_merge($result[$item['State']], $item);
} else {
$result[$item['State']] = $item;
}
}
$result = array_values($result);
print_r($result);
The output:
Array
(
[0] => Array
(
[State] => Utah
[users] => 5
[emails] => 18
)
[1] => Array
(
[State] => California
[users] => 10
[emails] => 28
)
[2] => Array
(
[State] => Arizona
[emails] => 32
)
)

Combine two arrays into a single array based on a common column value

I am trying to combine two arrays while respecting their shared value.
$array1 = array(
array("id" => "1","name"=>"John"),
array("id" => "2","name"=>"Peter"),
array("id" => "3","name"=>"Tom"),
array("id" => "12","name"=>"Astro")
);
$array2 = array(
array("id" => "1","second_name"=>"Lim"),
array("id" => "2","second_name"=>"Parker"),
array("id" => "3","second_name"=>"PHP")
);
My expected output:
$result = array(
array("id" => "1","name"=>"John","second_name"=>"Lim"),
array("id" => "2","name"=>"Peter","second_name"=>"Parker"),
array("id" => "3","name"=>"Tom","second_name"=>"PHP"),
array("id" => "12","name"=>"Astro")
);
I have made a try by
$arraycomb = array_unique(array_merge($array1,$array2), SORT_REGULAR);
My output is:
Array
(
[0] => Array
(
[id] => 1
[name] => John
)
[1] => Array
(
[id] => 2
[name] => Peter
)
[2] => Array
(
[id] => 3
[name] => Tom
)
[3] => Array
(
[id] => 12
[name] => Astro
)
[4] => Array
(
[id] => 1
[second_name] => Lim
)
[5] => Array
(
[id] => 2
[second_name] => Parker
)
[6] => Array
(
[id] => 3
[second_name] => PHP
)
)
How can I combine the key value inside same array? or how can I bring the expected output?
Note: I am trying for value instead of key ref: PHP Array Merge two Arrays on same key
Alternatively, you could use a foreach in this case then merge them if they share the same id key
With using reference &
foreach($array1 as &$value1) {
foreach ($array2 as $value2) {
if($value1['id'] == $value2['id']) {
$value1 = array_merge($value1, $value2);
}
}
}
echo '<pre>';
print_r($array1);
You can use array_map() for this. Try this -
function modifyArray($a, $b)
{
if (!empty($a) && !empty($b)) {
return array_merge($a, $b);
} else if (!empty($a) && empty($b)) {
return $a;
} else if (empty($a) && !empty($b)) {
return $b;
}
}
$new = array_map("modifyArray", $array1, $array2);
var_dump($new);
It will generate the new array will all the values in both arrays.if the first array's element is empty then the second array will be merged and vice-versa.
Assign temporary first level keys to your first array to aid in identifying rows. Then loop the second array and append the desired column value to the appropriate group. Re-index the array after looping with array_values().
Code: (Demo)
$result = array_column($array1, null, 'id');
foreach ($array2 as $row) {
$result[$row['id']]['second_name'] = $row['second_name'];
}
var_export(array_values($result));
This is a more direct approach than brute force scanning arrays with nested loops.
If all ids in the second array exist in the first array, then the following simpler line can be written inside the body of the foreach().
$result[$row['id']] += $row;

php array find duplicates, sum them up & delete duplicates

i have an array:
Array
(
[0] => Array
(
[setid] => 2
[income] => 100
)
[1] => Array
(
[setid] => 2
[income] => 120
)
[2] => Array
(
[setid] => 3
[income] => 700
)
)
i need to find entrys with the same setid, sum their income up and delete duplicate entrys - in the end it should look like this:
Array
(
[0] => Array
(
[setid] => 2
[income] => 220
)
[1] => Array
(
[setid] => 3
[income] => 700
)
)
does someone know a sophosticated solution for my problem or do i have to take the long road and do every step manually?
thanks and greetings
Just create a new array which you make fast adressable by using the setid as key. And reindex the array at the end.
$result = array();
foreach ($array as $val) {
if (!isset($result[$val['setid']]))
$result[$val['setid']] = $val;
else
$result[$val['setid']]['income'] += $val['income'];
}
$result = array_values($result); // reindex array
This should work:
$values = array();
foreach($array as $val) {
if(isset($values[$val['setid']])) {
$values[$val['setid']] += $val['income'];
} else {
$values[$val['setid']] = $val['income'];
}
}
//all values are now in $values array, keys are setid and values are income
Write your own function, that's no long road at all.
$result = array_reduce($originalArray, function($memo, $item){
isset($memo[$item['setid']])
? $memo[$item['setid']] = $item['income']
: $memo[$item['setid']] += $item['income'];
return $memo;
}, []);
You should use the array_unique function that php's official site offers.
An example:
<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
?>
Output:
Array
(
[a] => green
[0] => red
[1] => blue
)
To sum the duplicated values you can use the array_count_values function:
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Output would be:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)

Categories