Put nested array into one array - php

Suppose i have a array like this :
Array(
'1' => Array(
"ID" => 1,
"Name" => "name 1"
),
'2' => Array (
Array(
"ID" => 2,
"Name" => "name 2"
)
),
'3' => Array(
Array(
Array(
Array(
"ID" => 3,
"Name" => "name3"
)
)
),
'4' => Array (
Array {
"ID" => 4,
"Name" => "name 4"
),
Array(
"ID" => 5,
"Name" => "name 5"
),
Array(
"ID" => 6,
"Name" => "name 6"
)
);
number of sub-arrays is not ordered it may be 3, 4 or 5 etc...
and i wanted to get :
Array(
Array( "ID" => 1, "Name" => "name 1"),
Array( "ID" => 2, "Name" => "name 2"),
Array( "ID" => 3, "Name" => "name 3"),
Array( "ID" => 4, "Name" => "name 4"),
Array( "ID" => 5, "Name" => "name 5"),
Array( "ID" => 6, "Name" => "name 6"));
Is there an easy way to do this ?
EDIT :
Edited the above array to add :
'4' => Array (
Array {
"ID" => 4,
"Name" => "name 4"
),
Array(
"ID" => 5,
"Name" => "name 5"
),
Array(
"ID" => 6,
"Name" => "name 6"
)
);
which aren't nested but i still want them to be in my final array.
Thanks.

//Assuming your data is in $in
$out=array();
foreach($in as $k=>$v) {
while ((is_array($v)) && (isset($v[0]))) $v=$v[0];
//See below for next line
$out[]=$v;
}
print_r($out);
With the marked line being either $out[$k]=$v; or $out[]=$v; depending on wether you want to keep the 1st-level keys. In your desired output you do not ,so use the shown version
Edit
With you changed input array, you need to do something like
function addtoarray($inarray, &$outarray) {
foreach ($inarray as $i) {
if (!is_array($i)) continue;
if (isset($i['ID'])) $outarray[]=$i;
else addtoarray($i,$outarray);
}
}
$out=array();
addtoarray($in,$out);
print_r($out);
This was tested against your new input data

You could recurse through the array and check for the ID field.
function combine_array(array $src, array &$dest)
{
if( isset( $src['ID'] ) ) {
$dest[] = $src;
return;
}
foreach( $sub in $src ) {
combine_array( $sub, $dest );
}
}
Just wrote this off the top of my head, no testing, so it might have a few problems. But that's the basic idea.

This may work for you, assuming $array is the variable and php 5.3
//process
$array = array_map(function($block) {
$return = '';
foreach ($block as $sub) {
if (true === isset($sub['ID']) {
$return = $block;
break;
}
}
return $block;
}, $array);
array_filter($array); //remove empty elements

Wrote up a quick recursive function. You'll need to write any appropriate error handling and check the logic, since a discrepancy in your data could easily turn this into an infinite loop:
$output = array();
foreach ( $data as $d ) {
$output[] = loop_data( $d );
}
function loop_data( $data ) {
// Check if this is the right array
if( ! array_key_exists( "ID", $data ) ) {
// Go deeper
$data = loop_data( $data[0] );
}
return $data;
}

Related

Intersection of one multidimensional arrays in PHP

I have the following array :
$output = array(
1507073550 => array(
0 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "11863258101"
"username" => "rasouli680"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70326284_949495768737898_5241573836020776960_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
2 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
16528062 => array(
0 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
)
and I want to intersection of keys of this array. get first key "1507073550" and second key "16528062" and intersect all of their data.
it's not always have 2 keys, it might have +2 keys, i wrote this code but I'm getting array to string conversion error.
$keys = array_keys($output);
foreach ($keys as $index => $values)
{
$current_value = $output[$values]; // or $current_value = $a[$keys[$index]];
$next_key = next($keys);
$next_value = $output[$next_key] ?? null; // for php version >= 7.0
$a[] = array_intersect_assoc($current_value,$next_value);
}
and I'm expecting this result :
array(
0 => array(
"userid" => "1507073550"
"username" => "ma_alikhani"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/75538099_557824008392923_8054831368279949312_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
1 => array(
"userid" => "16528062"
"username" => "alireza"
"type" => "comment"
"profile_image" => "https://instagram.fgbb2-1.fna.fbcdn.net/v/t51.2885-19/s150x150/70597112_740563976416368_5253996423334068224_n.jpg?_nc_ht=instagram.fgbb2-1.fna.fbcdn.net&_nc_ohc"
)
)
I really don't know how to do it !
I'd be appreciated for your helps.
function intersect(array $src, array $keys)
{
// Require that both $src and $keys have data
if (!$src || !$keys) {
return [];
}
// Hold the users for each key in $keys
$sets = [];
// Store the users from $src to $sets as dictated by $keys
foreach ($keys as $key) {
if (isset($src[$key])) {
// Re-key the list of users with their user id
$userIds = array_column($src[$key], 'userid');
$sets[$key] = array_combine($userIds, $src[$key]);
}
}
if (count($sets) !== count($keys)) {
// Up to you if you want to require that all keys must be valid/present in the $src
}
// Get the users present in all of the set dictated by $keys
$users = call_user_func_array('array_intersect_key', $sets);
return $users;
};
To use:
$output = [ ... ]; // $ouput in the question
$keys = [1507073550, 16528062]; // see question
$users = intersect($output, $keys);

Dynamic create parent-child relationship array based on another table field values

There are 2 arrays Say
1. Groups
$groups = array("user", "account", "client")
2. Results
$results = array(
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C1"
),
1 => array(
"user" => "U1",
"account" => "A2",
"client" => "C1"
),
0 => array(
"user" => "U1",
"account" => "A3",
"client" => "C1"
),
0 => array(
"user" => "U1",
"account" => "A2",
"client" => "C2"
),
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C4"
),
0 => array(
"user" => "U1",
"account" => "A1",
"client" => "C5"
),
0 => array(
"user" => "U1",
"account" => "A2",
"client" => "C5"
)
) ;
I want following OUTPUT
$output = array(
"U1" => array(
"A1" => array(C1,C4,C5),
"A2" => array(C1,C2,C5),
"A3" => array(C1)
)
);
The Groups array values are dynamic and may be any order. I want output in order the first value of groups array is the parent element of Output array and second value of group array is the child of parent Output array and so on.
I hope you are using PHP greater or equal to 5.6. There we have ... (splat operator) that will come really handy:
$output = [];
array_map(function (...$keys) use (&$output) {
// Pop the last key, because it is actually a value.
$value = array_pop($keys);
// Prepare "element" to assign the value to using keys and references.
$element = &$output;
while($key = array_shift($keys)) {
if (!isset($element[$key])) {
$element[$key] = [];
}
$element = &$element[$key];
}
$element[] = $value;
}, ...array_map(function ($group) use ($results) {
return array_column($results, $group);
}, $groups));
Here is working demo.
In short, we take advantage of the ability of array_map to take any number of arrays as arguments and traverse them kinda parallelly.
Simply make a foreach loop like this
$new = array();
foreach($results as $key=>$value){
$new[$value["user"]][$value["account"]][] = $value["client"];
}
print_r($new);
live demo : https://eval.in/857969
Using $groups : https://eval.in/857970
$new = array();
foreach($results as $key=>$value){
$new[$value[$groups[0]]][$value[$groups[1]]][] = $value[$groups[2]];
}
Example for multiple user's : https://eval.in/857973
Update
For dynamic groups array : You can use eval if you are not interacting user input here. : https://eval.in/858306

Remove from multidimensional array if has seen id before in an basic array

I would like in php to stop duplicate messages by logging msgid to a text file using something like this file_put_contents("a.txt", implode(PHP_EOL, $array1), FILE_APPEND);
and then converting it back to an array using $array1 = file("a.txt"); I would also like to delete messages from the array if they are from a set name
I know how to convert json to an array $array1 = json_decode($json, true);
Json Reply from an api that I cannot control
{
"API": "Online",
"MSG": [
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
},
{
"info": {
"name": "example"
},
"msg": "example",
"msgid": "example"
}
]
}
Hi use the following code, first test it out accordingly
$uniqueMessages = unique_multidim_array($messages,'msg');
Usage : Pass the key as the 2nd parameter for which you need to check the uniqueness of array.
<?php
/* Function to handle unique assocative array */
function unique_multidim_array($array, $key) {
/* temp array to hold unique array */
$temp_array = array();
/* array to hold */
$i = 0;
/* array to hold the key for unique array */
$key_array = array();
foreach($array as $val) {
if (!in_array($val[$key], $key_array)) {
$key_array[$i] = $val[$key];
$temp_array[$i] = $val;
}
$i++;
}
return $temp_array;
}
$messages = array(
0 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
),
1 => array(
'info' => array(
'name' => 'example 1'
),
'msg' => 'example 1',
'msgid' => 'example 1'
),
3 => array(
'info' => array(
'name' => 'example'
),
'msg' => 'example',
'msgid' => 'example'
)
);
echo '<pre>';
echo '*****************BEFORE***********************<br/>';
var_dump($messages);
echo '*****************AFTER***********************<br/>';
$uniqueMessages = unique_multidim_array($messages,'msg');
var_dump($uniqueMessages);
This works for me this is an modded function click here for original function
function RemoveElementByArray($array, $key, $seen){
foreach($array as $subKey => $subArray){
if(in_array($subArray[$key], $seen)){
unset($array[$subKey]);
}
}
return $array;
}
Example:
$array = array(
array("id" => "1", "name" => "example1"),
array("id" => "2", "name" => "example2"),
array("id" => "3", "name" => "example3"));
$SeenArray = array("1", "2");
print_r(RemoveElementByArray($array, "id", $SeenArray));
Result:
Array
(
[2] => Array
(
[id] => 3
[name] => example3
)
)

PHP multidimensional array search key by value

For example a multidimensional array like an example below
$arr = array(
[H1] => array(
"name" => "A"
"title" => "T1"
)
[H2] => array(
"name" => "B"
"title" => "B1"
)
)
Let's say I would like to search name which equals to A in $arr and if it's matched, the searching should return the key which is H1
How can I do that in php ?
I tried array_keys($arr, "A") but it returns me with an array instead of the key.
This may help -
$arr = array(
'H1' => array(
"name" => "A",
"title" => "T1",
),
'H2' => array(
"name" => "B",
"title" => "B1",
)
);
// Generate a new array with 'keys' and values in 'name'
$new = array_combine(array_keys($arr), array_column($arr, 'name'));
// Search in that new array
$search = array_search('A', $new);
var_dump($search);
Output
string(2) "H1"
Demo
Another simple way would be -
$serach= false;
foreach($arr as $key => $val) {
if($val['name'] == 'A') {
$search= $key;
break;
}
}
var_dump($search);

PHP: How to update/extend an multidimensional Array recursive and on-the-fly?

I've a multidimensional array and would like to update/add some values, recursive. I'd like to avoid building a new array, if possible. But I've two main problems:
How to update the values "on-the-fly"? It should be possible with the &-operator.
How to get values to extend the array if the function getDetails() is out of scope.
My alternative is to rebuild everything, but I think there should be a more clean possibility.
I've added some pseudocode and hope it's not too weird. I appreciate your help!
Here's the fiddle: http://phpfiddle.org/main/code/m2g-ign
PHP
// build the array
$myArray = array(
array(
"id" => 1,
"name" => "A (Level 1)",
"children" => array(
array(
"id" => 3,
"name" => "C (Level 2)",
"children" => array(
"id" => 4,
"name" => "D (Level 3)",
"children" => null
)
),
array(
"id" => 6,
"name" => "F (Level 2)",
"children" => array(
"id" => 7,
"name" => "G (Level 3)",
"children" => null
)
)
)
),
array(
"id" => 2,
"name" => "B (Level 1)",
"children" => array(
array(
"id" => 5,
"name" => "E (Level 2)",
"children" => null
)
)
)
);
// returns detailed data, important: it's out of scope
function getDetails($id) {
// select dataset from DB
// ...
return $details;
}
// loop the array
$RAI = new RecursiveArrayIterator($myArray);
function updateMyArray($iterator) {
while ($iterator->valid()) {
if ($iterator->hasChildren()) {
// recursive
updateMyArray($iterator->getChildren());
} else {
/*
// 1. set "name" to uppercase
// Pseudocode:
$iterator->activeChild()->change(function(&$value) {
$value = toUpperCase($value);
});
// 2. add Array
// Pseudocode:
$id = $iterator->activeChild()->getValue("id");
$iterator->activeChild()->add("details", getDetails($id)); // getDetails() is out of scope, I guess
*/
}
$iterator->next();
}
}
echo "<strong>Before:</strong><pre>";
print_r($myArray);
echo "</pre>";
iterator_apply($RAI, 'updateMyArray', array($RAI));
echo "<strong>After:</strong><pre>";
print_r($myArray);
echo "</pre>";

Categories