PHP array_intersect / array_diff / combine array - php

$arr[] = array('title' => 'Overview');
$arr[] =array('title' => 'General');
$arr[] =array('title' => 'History');
$arr[] =array('title' => 'Construction');
$arr[] =array('title' => 'Plan');
$arr[] =array('title' => 'Other');
$info_arr[] = array("title" => "General", text => "value1");
$info_arr[] = array("title" => "History", text => "value1");
$info_arr[] = array("title" => "Construction", text => "value1");
$info_arr[] = array("title" => "Plan", text => "value1");
I need to be able merge these arrays together.So they look something like this. As I will need to loop thru the consolidated array. Other, Overview do not have any text values but still need to placed into the array.
$new_arr[] = array("title" => "General", text => "value1", "title" => "History", text => "value1", "title" => "Construction", text => "value1"
,"title" => "Plan", text => "value1","title" => "Overview", text => "","title" => "Other", text => "");
I have tried for loops (using count value), foreach loops, I thought array_intersect or array_diff don't see to solve the issue. This should not be so difficult, but I'm trying to piece together some really bad legacy code. Or the cube/florescent lights might have finally got to me.
Update:
while ($stmt->fetch()) {
$arr[] = array("title" => $Title);
}
and
while ($dstmt->fetch()) {
$info_arr[] = array("title" => $descriptionType, "descriptiontext" => $descriptionText); , "descriptiontext" => $val );
}
$dstmt & $stmt are queries.
I thought this would work but not so much
$r = array_intersect($arr, $info_arr);
var_dump($r);
Something like this Let me clarify:
$new_arr = array(array("title" => "General", text => "value1"),
array("title" => "History", text => "value1"),
array("title" => "Construction", text => "value1"),
array("title" => "Plan", text => "value1"),
array("title" => "Overview", text => ""),
array("title" => "Other", text => "")
);

If you want to work with these two arrays, you can just use the title as the key in $r.
foreach (array_merge($arr, $info_arr) as $x) {
$r[$x['title']]['title'] = $x['title'];
$r[$x['title']]['text'] = isset($x['text']) ? $x['text'] : '';
}
Or, you can go back a step and avoid having separate arrays by building the $r array in the same manner as you fetch your query results:
while ($stmt->fetch()) {
$r[$Title] = array('title' => $Title, 'text' => '');
}
while ($dstmt->fetch()) {
$r[$descriptionType] = array("title" => $descriptionType, "text" => $descriptionText);
}
Or, ideally, you could go back another step and avoid having separate queries by using a JOIN to get the same results in one query, but there's nothing in the question on which to base any specific suggestion for that.

As stated in the comments, the exact $new_arr you're requesting isn't possible. However, I think this will give you a similar result that should work for your purposes:
foreach ($info_arr as $infoArray) {
$found = array_search(array('title' => $infoArray['title']), $arr);
if (false !== false) {
unset($arr[$found]);
}
}
$new_arr = array_merge($info_arr, $arr);
It works by removing the "duplicates" from the original $arr before doing the array_merge().
If it's important to add an empty text value for the remaining items in $arr, do this before the array_merge():
foreach ($arr as &$arrArray) {
$arrArray['text'] = '';
}
The resulting array will look like this:
$new_arr[] = array(
array(
'title' => 'General',
'text' => 'value1',
),
array(
'title' => 'History',
'text' => 'value1',
),
array(
'title' => 'Construction',
'text' => 'value1',
),
array(
'title' => 'Plan',
'text' => 'value1',
),
array(
'title' => 'Overview',
'text' => '',
),
array(
'title' => 'Other',
'text' => '',
),
);

Related

Assign values in array based on array keys

How to modify an array based on the value as key?
array(
array(
"name" => "BIBAR",
"cutoff" => 20220725,
"totals" => 5614
),
array(
"name" => "BIBAR",
"cutoff" => 20220810,
"totals" => 5614
),
array(
"name" => "BIBAR",
"cutoff" => 20220825,
"totals" => 5614
)
);
I tried the following but it's not working:
foreach($cutoffs as $catoff) {
$ii = 0;
$sums[$ii][$catoff] = array_filter($array, function($val){
return $val['cutoff'] === $catoff ? $val['totals'] : $val;
});
$ii++;
}
My desired array:
array(
'20221025' => array(
12345,
12343,
24442
),
'20221110' => array(
3443,
744334
)
)
I'm stuck here for hours ... Please help
IF the "name" is irrelevant, I think also the previous answer should be fine.
If this code does "not work", then your explanation might be wrong, so you need to either explain better, or give us more examples - please mind that in your example the input and output are very different - the input you gave does not match your ouput.
My code is:
$a = array(
array(
"name" => "BIBAR",
"cutoff" => 20220725,
"totals" => 5614
),
array(
"name" => "BIBAR",
"cutoff" => 20220810,
"totals" => 5614
),
array(
"name" => "BIBAR",
"cutoff" => 20220725,
"totals" => 1234
)
);
print_r($a);
echo "\n================================\n\n";
$newArr = [];
foreach ($a as $k => $vArr) {
// maybe some validation would be useful here, check if they keys exist
$newArr[$vArr['cutoff']][] = $vArr['totals'];
}
print_r($newArr);
function changeArr($data){
$new = [];
foreach ($data as $v){
$new[$v['cutoff']][] = $v['totals'];
}
return $new;
}

Regroup multidimensional array to reverse presentation of many-to-many relationship

I need to perform iterated explosions on values in one column of my two dimensional array, then re-group the data to flip the relational presentation from "tag name -> video id" to "video id -> tag name".
Here is my input array:
$allTags = [
[
"name" => "TAG-ONE",
"video" => "64070,64076,64110,64111",
],
[
"name" => "TAG-TWO",
"video" => "64070,64076,64110,64111",
],
[
"name" => "TAG-THREE",
"video" => "64111",
]
];
I want to isolate unique video ids and consolidate all tag names (as comma-separayed values) that relate to each video id.
Expected output:
$allTagsResult = [
[
"name" => "TAG-ONE,TAG-TWO",
"video" => "64070",
],
[
"name" => "TAG-ONE,TAG-TWO",
"video" => "64076",
],
[
"name" => "TAG-ONE,TAG-TWO",
"video" => "64110",
],
[
"name" => "TAG-ONE,TAG-TWO,TAG-THREE",
"video" => "64111",
],
];
Somehow I did it by checking the value using nested loops but I wish to know if you guys can suggest any shortest method to get the expected output.
If you want to completely remove foreach() loops, then using array_map(), array_walk_recursive(), array_fill_keys() etc. can do the job. Although I think that a more straightforward answer using foreach() would probably be faster, but anyway...
$out1 = array_map(function ($data) {
return array_fill_keys(explode(",", $data['video']), $data['name']); },
$allTags);
$out2 = [];
array_walk_recursive( $out1, function ( $data, $key ) use (&$out2) {
if ( isset($out2[$key])) {
$out2[$key]['name'] .= ",".$data;
}
else {
$out2[$key] = [ 'name' => $data, 'video' => $key ];
}
} );
print_r($out2);
will give...
Array
(
[64070] => Array
(
[name] => TAG-ONE,TAG-TWO
[video] => 64070
)
[64076] => Array
(
[name] => TAG-ONE,TAG-TWO
[video] => 64076
)
[64110] => Array
(
[name] => TAG-ONE,TAG-TWO
[video] => 64110
)
[64111] => Array
(
[name] => TAG-ONE,TAG-TWO,TAG-THREE
[video] => 64111
)
)
if you want to remove the keys, then
print_r(array_values($out2));
The code could be compressed by piling all of the code onto single lines, but readability is more useful sometimes.
Another method if you don't like looping:
$video_ids = array_flip(array_unique(explode(",",implode(",",array_column($allTags,'video')))));
$result = array_map(function($id){
return ['name' => '','video' => $id];
},array_flip($video_ids));
array_walk($allTags,function($tag_data) use (&$result,&$video_ids){
$ids = explode(",",$tag_data['video']);
foreach($ids as $id) $result[$video_ids[$id]]['name'] = empty($result[$video_ids[$id]]['name']) ? $tag_data['name'] : $result[$video_ids[$id]]['name'] . "," . $tag_data['name'];
});
Demo: https://3v4l.org/vlIks
Below is one way of doing it.
$allTags = [
'0' => [
"name" => "TAG-ONE",
"video" => "64070,64076,64110,64111",
],
'1' => [
"name" => "TAG-TWO",
"video" => "64070,64076,64110,64111",
],
'2' => [
"name" => "TAG-THREE",
"video" => "64111",
]
];
$allTagsResult = array();
$format = array();
foreach( $allTags as $a ) {
$name = $a['name'];
$videos = explode(',', $a['video']);
foreach( $videos as $v ) {
if( !isset( $format[$v]) ) {
$format[$v] = array();
}
$format[$v][] = $name;
}
}
foreach( $format as $video => $names) {
$allTagsResult[] = array('name' => implode(',', $names), 'video' => $video);
}
echo '<pre>';
print_r($allTagsResult);
die;
You can check Demo
I am typically in favor of functional style coding, but for this task I feel it only serves to make the script harder to read and maintain.
Use nested loops and explode the video strings, then group by those video ids and concatenate name strings within each group. When finished iterating, re-index the array.
Code: (Demo)
$result = [];
foreach ($allTags as $tags) {
foreach (explode(',', $tags['video']) as $id) {
if (!isset($result[$id])) {
$result[$id] = ['video' => $id, 'name' => $tags['name']];
} else {
$result[$id]['name'] .= ",{$tags['name']}";
}
}
}
var_export(array_values($result));
Output:
array (
0 =>
array (
'video' => '64070',
'name' => 'TAG-ONE,TAG-TWO',
),
1 =>
array (
'video' => '64076',
'name' => 'TAG-ONE,TAG-TWO',
),
2 =>
array (
'video' => '64110',
'name' => 'TAG-ONE,TAG-TWO',
),
3 =>
array (
'video' => '64111',
'name' => 'TAG-ONE,TAG-TWO,TAG-THREE',
),
)

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
)
)

Creating array from array

I have following array.
{#11950
+"attributes": array:3 [
0 => {#608
+"attribute_value": "test123"
+"attribute_name": "name"
}
1 => {#556
+"attribute_value": "foo moo"
+"attribute_name": "lastname"
}
2 => {#605
+"attribute_value": "sample moo"
+"attribute_name": "email"
}
3 => {#606
+"attribute_value": "holo"
+"attribute_name": "adress"
}
]
}
I would like to convert it like follow
$a = array(
'name' => 'test123',
'lastname' => 'foo moo',
'email' => 'sample moo',
'address' => 'holo
);
I will do same operation countless time so I believe there should be a proper solution rather then looping all values and checking out attribute_name with if else etc.
You can do this with a single call to array_column, by using the $index_key parameter:
$arr = [
['attribute_name' => 'foo', 'attribute_value' => 123],
['attribute_name' => 'bar', 'attribute_value' => 456],
['attribute_name' => 'baz', 'attribute_value' => 789],
];
$result = array_column($arr, 'attribute_value', 'attribute_name');
See https://eval.in/705641
Short but simple:
$result = array_combine(array_column($arr, 'attribute_name'), array_column($arr, 'attribute_value'));
You could do a simple foreach loop and build the result array :)
$result = [];
foreach ($array as $attr) {
$result[$attr['attribute_name']] = $attr['attribute_value'];
}
This reads a bit better. It probably doesn't make much different in most cases, but I don't think it's as performant as just a simple foreach ;)
$result = array_combine(
array_column($array, 'attribute_name'),
array_column($array, 'attribute_value')
);

Appending an array to a multi dimensional array fails silently PHP?

I am trying to append an array to another one in a multi dimensional array:
This is the multi dimensional array:
$info[] = array(
'key' => $row['id'],
'master' => array(
'name' => $row['master_name'],
"detail" => array()
)
);
I has a key which is the master id, and a master item which is an array with a name and another array with the detail (at the first time is empty).
But when I try to add to the $info['master']['detail'] array another array with a detail, like this:
$info['master']['detail'][] = array("name" => "A detail name",
"value" => "A detail value");
Nothing is added... How is that possible?
EDIT: the foreach loops that should add the details to the master:
foreach ($details as $detail)
{
$name = $detail['detail_name'];
$value = $detail['detail_value'];
if ($info['key'] == $detail['id']) {
$info['master']['detail'][] = array("name" => $name,
"value" => $value);
}
}
I'm not sure I understand but when I see your examples, I think it is a problem of index:
Try to replace
$info[] = array(
'key' => $row['id'],
'master' => array(
'name' => $row['master_name'],
"detail" => array()
)
);
$info['master']['detail'][] = array("name" => "A detail name",
"value" => "A detail value");
by
$info = array( 'key' => $row['id'],
'master' => array('name' => $row['master_name'],,
"detail" => array())
);
$info['master']['detail'] = array("name" => "A detail name",
"value" => "A detail value");
and to add a new value :
$info['master']['detail']['foo'] = "A detail foo";

Categories