How to consolidate duplicate elements of this array in PHP? - php

I have an array like this:
$array = array(
0 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "memory"),
1 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "cpu"),
2 => array("ordernumber" => "1", "name" => "John", "product" => "desktop", "component" => "cpu"),
3 => array("ordernumber" => "2", "name" => "Pete", "product" => "monitor", "component" => "")
);
It contains data from different orders, but as you can see an order can contain multiple purchased products, and each product can contain different 'components'. There's alot of duplicate data in this array, so I would like to turn it into this:
$array = array(
0 => array(
"order" => array(
"ordernumber" => "1", "name" => "John"
),
"products" => array(
0 => array(
"name" => "laptop",
"components" => array("memory", "cpu")
),
1 => array(
"name" => "desktop",
"components" => array("cpu")
)
)
),
1 => array(
"order" => array(
"ordernumber" => "2", "name" => "Pete"
),
"products" => array(
0 => array(
"name" => "monitor",
"components" => array()
)
)
)
);
What would be a good way to do this?

Please use below code to make the solution what you want
<?php
$array = array(
0 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "memory"),
1 => array("ordernumber" => "1", "name" => "John", "product" => "laptop", "component" => "cpu"),
2 => array("ordernumber" => "1", "name" => "John", "product" => "desktop", "component" => "cpu"),
3 => array("ordernumber" => "2", "name" => "Pete", "product" => "monitor", "component" => "")
);
$final_array = [];
foreach($array as $k=>$v){
$final_array[$v['ordernumber']]['order']['ordernumber'] = $v['ordernumber'];
$final_array[$v['ordernumber']]['order']['name'] = $v['name'];
$final_array[$v['ordernumber']]['products'][$v['product']]['name'] = $v['product'];
$final_array[$v['ordernumber']]['products'][$v['product']]['components'][] = $v['component'];
}
// You can skip this foreach if there will not metter of KEY of an array in your code!
$final_array = array_values($final_array);
foreach($final_array as $k=>$v){
$final_array[$k]['products'] = array_values($final_array[$k]['products']);
}
echo "<pre>";
print_r($final_array);
?>
its should work!!

Related

Construct an associative array from 2 other arrays, and linked by a common key

Problem:
I would like to combine 2 associative arrays to make one. To link these arrays, the ID key is present in both.
Input:
To retrieve my contacts with api call, I have to do 2 requests :
First to retrieve contacts with Id, and email adresse
Second to get some informations like name, city etc.
The first one return an array like this :
$contactArray = array(
array(
"CreatedAt" => "2019-04-12T11:53:26Z",
"DeliveredCount" => 0,
"Email" => "terry#example.org",
"ExclusionFromCampaignsUpdatedAt" => "2019-04-28T09:21:35Z",
"ID" => 1864410583,
"IsExcludedFromCampaigns" => false,
"IsOptInPending" => false,
"IsSpamComplaining" => false,
"LastActivityAt" => "2019-04-28T09:21:35Z",
"LastUpdateAt" => "2019-04-28T09:21:35Z",
"Name" => "",
"UnsubscribedAt" => "",
"UnsubscribedBy" => ""
),
array(
"CreatedAt" => "2019-04-12T12:39:30Z",
"DeliveredCount" => 0,
"Email" => "duane#example.org",
"ExclusionFromCampaignsUpdatedAt" => "",
"ID" => 1864410588,
"IsExcludedFromCampaigns" => false,
"IsOptInPending" => false,
"IsSpamComplaining" => false,
"LastActivityAt" => "2019-04-12T12:39:30Z",
"LastUpdateAt" => "2019-04-12T12:39:30Z",
"Name" => "",
"UnsubscribedAt" => "",
"UnsubscribedBy" => ""
)
);
The second call, return an array like
$contactDataArray =
array(
array(
"ContactID" => 1864410583,
"Data" => array(
array(
"Name" => "firstname",
"Value" => "Mark"
),
array(
"Name" => "city",
"Value" => "Miami"
),
array(
"Name" => "name",
"Value" => "Terry"
),
array(
"Name" => "phone",
"Value" => "555-5555"
)
),
"ID" => 1864410583
),
array(
"ContactID" => 1864410588,
"Data" => array(
array(
"Name" => "firstname",
"Value" => "Jane"
),
array(
"Name" => "city",
"Value" => "New York"
),
array(
"Name" => "name",
"Value" => "Duane"
),
array(
"Name" => "phone",
"Value" => "555-5555"
)
),
"ID" => 1864410588
)
);
In $contactArray, the ID key matches with ContactID key and ID key in $contactDataArray
Attempt:
I want an array formatted like this :
$output = array(
array(
"Email" => "terry#example.org",
"ID" => 1864410583,
"firstname" => "Mark",
"city" => "Miami",
"name" => "Terry",
"phone" => "555-5555"
),
array(
"Email" => "duane#example.org",
"ID" => 1864410588,
"firstname" => "Jane",
"city" => "New York",
"name" => "Duane",
"phone" => "555-5555"
)
);
I'm trying to achieve this with array_walk, but no succeed.
You can do this with foreach,
$result = [];
foreach ($contactDataArray as $key => $value) {
$ids = array_column($contactArray, "ID"); // fetching all values from contactArray
if (!empty(array_intersect([$value['ContactID'], $value['ID']], $ids))) { // checking if both satisfy the condition
$result[$key] = array_column($value['Data'], 'Value', 'Name'); // combining name and value
// searchng for key with matched ContactID
$result[$key]['Email'] = $contactArray[array_search($value["ContactID"], $ids)]['Email'];
$result[$key]['ID'] = $value["ContactID"];
}
}
Demo.
Can you please try with this?
$output = [];
for($i = 0; $i < count($contactDataArray); $i++) {
$arrIDandEmail = [
'Email' => isset($contactArray[$i]['Email']) ? $contactArray[$i]['Email'] : '',
'ID' => isset($contactDataArray[$i]['ID']) ? $contactDataArray[$i]['ID'] : ''
];
$arrData = array_column($contactDataArray[$i]["Data"], "Value", "Name");
$newArray = array_merge($arrIDandEmail, $arrData);
$output[] = $newArray;
}
For PHP >= 7.1 you can use array destructuring using list()
<?php
$output = [];
foreach ($contactDataArray as [
'ID' => $id,
'Data' => [
['Name' => $firstnameKey, 'Value' => $firstnameValue],
['Name' => $cityKey, 'Value' => $cityValue],
['Name' => $nameKey, 'Value' => $nameValue],
['Name' => $phoneKey, 'Value' => $phoneValue]
]
]) {
$output[] = [
"Email" => $contactArray[array_search($id, array_column($contactArray, 'ID'))]['Email'],
"ID" => $id,
$firstnameKey => $firstnameValue,
$cityKey => $cityValue,
$nameKey => $nameValue,
$phoneKey => $phoneValue
];
}
var_dump($output);
Demo
You can use array_walk,array_combine,array_column for the desired array as a result
$res = [];
array_walk($contactArray, function($v, $k) use ($contactDataArray,&$res)
{
$res[] = array_merge(['Email'=>$v['Email'],'ID'=>$v['ID']],
array_combine(
array_column($contactDataArray[$k]['Data'],'Name'),
array_column($contactDataArray[$k]['Data'],'Value')
)
);
});
echo '<pre>';
print_r($res);
DEMO

multi-dimensional array hierarchy

I like to know how can I get the hierarchy by the identifier.
This is an example :
$inputArray = array(
array(
"text" => "Dir1",
"parent_id" => "",
"id" => "1",
"filesize" => "109"
),array(
"text" => "dir2",
"parent_id" => "",
"id" => "2",
"filesize" => "88",
"children" => array(
"text" => "Dir3",
"parent_id" => "2",
"id" => "3",
"filesize" => "",
"children" => array(
"text" => "dir4",
"parent_id" => "3",
"id" => "4",
"filesize" => "",
"children" => array(
"text" => "dir5",
"parent_id" => "4",
"id" => "4",
"filesize" => ""
)
)
)
));
looking for this example :
dir3/dir4/dir5
function getText($array) {
$save[] = $array['text'];
if (isset($array['children'])) {
$save = array_merge($save, getText($array['children']));
}
return $save;
}
foreach($inputArray as $x) {
echo implode('/', getText($x)) . "\n";
}
result
Dir1
dir2/Dir3/dir4/dir5
demo

Add a dynamic key => value options in 3 level array option

I have an array as main options in my code.
In case, I want to add dynamic key => values into specific options array key.
This is my main options array:
$configarray1 = array(
"name" => "Addon",
"description" => "module for whmcs",
"version" => "1.1",
"author" => "Me",
"language" => "english",
"fields" => array(
"sender" => array (
"FriendlyName" => "Sender",
"Type" => "dropdown",
"Options" => strtolower($GatewaysIM),
"Description" => $getBalance,
"Default" => $Defaultsender,
),
"validateday" => array (
"FriendlyName" => "Days for Re-validation",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "90",
),
)
);
I want to add this sender array options in configarray1 fields key:
if($sender == 'sender1'){
$configarray2['fields'] = array(
"username" => array (
"FriendlyName" => "username",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "",
),
"password" => array (
"FriendlyName" => "password",
"Type" => "password",
"Size" => "25",
"Description" => "",
"Default" => "",
)
);
} elseif($sender == 'sender2'){
$configarray2['fields'] = array(
"line" => array (
"FriendlyName" => "line",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "",
)
);
}
Output array must be like this below when sender is sender1:
$configarray = array(
"name" => "Addon",
"description" => "module for whmcs",
"version" => "1.1",
"author" => "Me",
"language" => "english",
"fields" => array(
"sender" => array (
"FriendlyName" => "Sender",
"Type" => "dropdown",
"Options" => strtolower($GatewaysIM),
"Description" => $getBalance,
"Default" => $Defaultsender,
),
"username" => array (
"FriendlyName" => "username",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "",
),
"password" => array (
"FriendlyName" => "password",
"Type" => "password",
"Size" => "25",
"Description" => "",
"Default" => "",
),
"validateday" => array (
"FriendlyName" => "Days for Re-validation",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "90",
),
)
);
I tested array push but this adds a key in arrays first place and not in 'fields' key, my code was this $configarray = array_push($configarray1,$configarray2); but this not works !
I also tested sum of two arrays ($configarray = $configarray1 + $configarray2) but this is the same as array_push and returns wrong output for me.
How can i resolve this problem ?!
You should just declare it. You don't need a new variable.
Assuming you have the original array named as $configarray1, just:
if($sender == 'sender1'){
$configarray1['fields']['username'] = array(
"FriendlyName" => "username",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "",
);
$configarray1['fields']['password'] => array(
"FriendlyName" => "password",
"Type" => "password",
"Size" => "25",
"Description" => "",
"Default" => "",
);
} elseif($sender == 'sender2'){
$configarray1['fields']['line'] = array (
"FriendlyName" => "line",
"Type" => "text",
"Size" => "25",
"Description" => "",
"Default" => "",
);
}

Array to repeat

$a = array(
array(
"name" => "jack",
"data" => "123",
"link_uid" => "1",
),
array(
"name" => "jack",
"data" => "134",
"link_uid" => "2",
),
array(
"name" => "tom",
"data" => "567",
"link_uid" => "3",
),
array(
"name" => "tom",
"data" => "098",
"link_uid" => "4",
)
);
to
$a = array(
array(
"name" => "jack",
"data" => "123",
"link_uid" => "1",
),
array(
"name" => " ",
"data" => "134",
"link_uid" => "2",
),
array(
"name" => "tom",
"data" => "567",
"link_uid" => "3",
),
array(
"name" => " ",
"data" => "098",
"link_uid" => "4",
)
);
Do you want just repeated name to blank
<?php
$temp = array();
foreach($a as $key=>$value){
if(in_array($value["name"],$temp)){
$a[$key]["name"] = "";
}else {
$temp[] = $value["name"];
}
}
print_r($a);
?>
Live demo : https://eval.in/855975

Rearranging multidimensional array in PHP [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an array that I need to rearange a bit.
I am building a voice server status widget for pyrocms.
I use for querying the voice server -> https://github.com/Austinb/GameQ
I use for the template -> https://github.com/BorisMoore/jsrender
whit a static table i haven created this !
www.i.stack.imgur.com/4a3Am.png
I get an array return and it looks like this.:
Array (
"Ventrilo" => Array (
"name" => "The Evil Teddys",
"phonetic" => "The Evil Teddys",
"comment" => "",
"auth" => "1",
"maxclients" => "20",
"voicecodec" => "0,GSM 6.10",
"voiceformat" => "3,44 KHz, 16 bit",
"uptime" => "25799604",
"platform" => "Linux-i386",
"version" => "3.0.3",
"channelcount" => "7",
"teams" => Array (
"0" => Array (
"cid" => "846",
"pid" => "0",
"prot" => "0",
"name" => "<TET>",
"comm" => ""
),
"1" => Array (
"cid" => "847",
"pid" => "0",
"prot" => "0",
"name" => "#ISOLATIECEL",
"comm" => ""
),
"2" => Array (
"cid" => "848",
"pid" => "0",
"prot" => "0",
"name" => "Relax Take It Easy",
"comm" => ""
),
"3" => Array (
"cid" => "849",
"pid" => "846",
"prot" => "0",
"name" => "Foodfightkitchen",
"comm" => ""
),
"4" => Array (
"cid" => "850",
"pid" => "846",
"prot" => "0",
"name" => "WOW",
"comm" => ""
),
"5" => Array (
"cid" => "851",
"pid" => "849",
"prot" => "0",
"name" => "Bad Company",
"comm" => ""
),
"6" => Array(
"cid" => "852",
"pid" => "850",
"prot" => "0",
"name" => "The G Channel",
"comm" => ""
)
),
"clientcount" => "3",
"players" => Array (
"0" => Array (
"admin" => "1",
"cid" => "846",
"phan" => "0",
"ping" => "18",
"sec" => "345345",
"name" => "Shorty*",
"comm" => ""
),
"1" => Array (
"admin" => "1",
"cid" => "851",
"phan" => "0",
"ping" => "20",
"sec" => "11988",
"name" => "Swifty",
"comm" => ""
),
"2" => Array (
"admin" => "1",
"cid" => "846",
"phan" => "0",
"ping" => "30",
"sec" => "678674",
"name" => "The1one12",
"comm" => ""
)
),
"gq_online" => "0",
"gq_address" => "172.0.0.1",
"gq_port" => "3812",
"gq_prot" => "ventrilo",
"gq_type" => "ventrilo"
)
and I want my end result to be like this:
cid = Channel ID
pid = Parent ID
Array (
"Ventrilo" => Array (
"name" => "The Evil Teddys",
"phonetic" => "The Evil Teddys",
"comment" => "",
"auth" => "1",
"maxclients" => "20",
"voicecodec" => "0,GSM 6.10",
"voiceformat" => "3,44 KHz, 16 bit",
"uptime" => "25799604",
"platform" => "Linux-i386",
"version" => "3.0.3",
"channelcount" => "7",
"teams" => Array (
"0" => Array (
"cid" => "846",
"pid" => "0",
"prot" => "0",
"name" => "<TET>",
"comm" => "",
"players" => Array (
"0" => Array (
"admin" => "1",
"cid" => "846",
"phan" => "0",
"ping" => "18",
"sec" => "345345",
"name" => "Shorty*",
"comm" => "vet verwacht je niet"
),
"1" => Array (
"admin" => "1",
"cid" => "846",
"phan" => "0",
"ping" => "30",
"sec" => "678674",
"name" => "The1one12",
"comm" => "grappig !"
)
),
"teams" => Array(
"0" => Array (
"cid" => "849",
"pid" => "846",
"prot" => "0",
"name" => "Foodfightkitchen",
"comm" => "",
"players" => Array (),
"teams" => Array(
"0" => Array (
"cid" => "851",
"pid" => "849",
"prot" => "0",
"name" => "Bad Company",
"comm" => "",
"players" => Array (
"0" => Array (
"admin" => "1",
"cid" => "851",
"phan" => "0",
"ping" => "20",
"sec" => "11988",
"name" => "Swifty",
"comm" => "nu nog Dynamisch"
)
),
"teams" => Array(
)
)
)
),
"1" => Array (
"cid" => "850",
"pid" => "846",
"prot" => "0",
"name" => "WOW",
"comm" => "",
"players" => Array (),
"teams" => Array(
"0" => Array(
"cid" => "852",
"pid" => "850",
"prot" => "0",
"name" => "The G Channel",
"comm" => "",
"players" => Array (),
"teams" => Array(
)
)
)
)
)
),
"1" => Array (
"cid" => "847",
"pid" => "0",
"prot" => "0",
"name" => "#ISOLATIECEL",
"players" => Array (),
"teams" => Array(
)
),
"2" => Array (
"cid" => "848",
"pid" => "0",
"prot" => "0",
"name" => "Relax Take It Easy",
"comm" => "",
"players" => Array (),
"teams" => Array(
)
)
),
"clientcount" => "3",
"gq_online" => "1",
"gq_address" => "213.163.76.130",
"gq_port" => "3812",
"gq_prot" => "ventrilo",
"gq_type" => "ventrilo"
)
How can I achieve this ? I have tried many things but nothing with this end result.
what i have now.
$teamArrayConverted['teams'] = convertTeamArray($serverstatus['teams']);
unset($serverstatus['players'], $serverstatus['teams']);
$results = array_merge_recursive($serverstatus, $teamArrayConverted);
function convertTeamArray ($array) {
// First, convert the array so that the keys match the ids
$reKeyed = array();
foreach ($array as $item) {
$reKeyed[(int) $item['cid']] = $item;
}
//print_r($reKeyed);
// Next, use references to associate children with parents
foreach ($reKeyed as $id => $item) {
if (isset($item['pid'], $reKeyed[(int) $item['pid']])) {
$reKeyed[(int) $item['pid']]['teams'][] =& $reKeyed[$id];
}
}
//print_r($reKeyed);
// Finally, go through and remove children from the outer level
foreach ($reKeyed as $id => $item) {
if ($item['pid'] != '0') {
//print_r($reKeyed[$id]);
unset($reKeyed[$id]);
}
}
return array_values($reKeyed);
}
It works in principle like this:
You make each node identifiable by it's numeric id and store it in a hash so it's accessible by it's id.
You take a new hash and insert all elements incl. their children as needed.
In detail discussion of the code is here: Converting an array from one to multi-dimensional based on parent ID values:
// key the array by id
$keyed = array();
foreach($array as &$value)
{
$keyed[$value['id']] = &$value;
}
unset($value);
$array = $keyed;
unset($keyed);
// tree it
$tree = array();
foreach($array as &$value)
{
if ($parent = $value['parent_id'])
$array[$parent]['children'][] = &$value;
else
$tree[] = &$value;
}
unset($value);
$array = $tree;
unset($tree);
var_dump($array); # your result
Replace the names with what you have as variable names and keys.
Create an array based on the pid from the current array which you can use to loop through the children based on the id.
$arr = array(...definition from your post....);
foreach($arr["teams"] as $team)
$teamchildren[$team[pid]][]=$team;
print_r($teamchildren);
Now you can loop through the $teamchildren[0] array and call a function recursively to build the nested team structure under each of the teams
The same concept could be applied to the players but changing the parent in this case to be the cid
(above code is not tested)

Categories