Insert Array to Array Collection without looping - php

I have two array..
Array 1
$arr1 = array(
'task' => 'delete'
)
Array 2
$arr2 = array(
array(
'id' => '1',
'type' => 'post',
),
array(
'id' => '2',
'type' => 'category',
),
array(
'id' => '1',
'type' => 'tag',
),
);
How I insert Array 1 to all Array 2 collection, so the results is.
$arr2 = array(
array(
'id' => '1',
'task' => 'delete',
'type' => 'post',
),
array(
'id' => '2',
'task' => 'delete',
'type' => 'category',
),
array(
'id' => '1',
'task' => 'delete',
'type' => 'tag',
),
);
I can be easily to get the results by using looping, but I want to achieve it not using looping.
Any suggestion ?
Thank you :)

In order to push arraay1 in array2 all indexes, you can use the array_walk with a combination of array merge, you can see below code for instance
<?php
$array1 = array(
'task' => 'delete',
'before' =>'test'
);
$array2=array(
array(
'id' => '1',
'type' => 'post',
),
array(
'id' => '2',
'type' => 'category',
),
array(
'id' => '1',
'type' => 'tag',
),
);
array_walk($array2, function(&$newarray) use ($array1) {
$newarray = array_merge($newarray, $array1);
});
print_r($array2);
?>
array_walk -Apply a user supplied function to every member of an array while array_merge, Merge two arrays into one array
Result
Array (
[0] => Array ( [id] => 1 [type] => post [task] => delete [before] => test )
[1] => Array ( [id] => 2 [type] => category [task] => delete [before] => test )
[2] => Array ( [id] => 1 [type] => tag [task] => delete [before] => test ) )
Git Hub
https://github.com/fahadpatel/insert-array-into-array-without-loop
DEMO

You can use array_walk to skip writing the loop.
$arr1 = array(
'task' => 'delete'
);
$arr2 = array(
array(
'id' => '1',
'type' => 'post',
),
array(
'id' => '2',
'type' => 'category',
),
array(
'id' => '1',
'type' => 'tag',
),
);
array_walk($arr2, function(&$item) use ($arr1) {
$item = array_merge($item, $arr1);
});
You can see the documentation for array_walk here.

You may use array_map. It's looping behind the scenes, though (no real way around it), but at least you don't have to do it yourself:
$arr3 = array_map(static function ($entry) use ($arr1) {
return $entry + $arr1;
}, $arr2);
PHP 7.4 version:
$arr3 = array_map(static fn($entry) => $entry + $arr1, $arr2);
Demo: https://3v4l.org/2u2SR

Related

Create an array from an array based on value and include matches within as an array

I'm wanting to group my data by a specific value (parent name) and then merge all the items that share the same parent name under a "items" array
However it's overwriting the items array, not adding to it, so for example "items" in the output should have multiple items not just one.
Any ideas?
$result = array();
foreach ($page->products_codes as $option) {
$result[$option->parent->name]["title"] = $option->parent->title;
$result[$option->parent->name]["items"] = $option->title;
}
Outputs as:
array (
'fixture' =>
array (
'title' => 'Fixture',
'items' => 'Pinhole90 Fixed with LED51',
),
'finish' =>
array (
'title' => 'Finish',
'items' => 'RAL',
),
'ip-rating' =>
array (
'title' => 'IP Rating',
'items' => 'IP54',
),
'emergency' =>
array (
'title' => 'Emergency',
'items' => 'Maintained 3hr Self Test',
),
'installation' =>
array (
'title' => 'Installation',
'items' => 'Plaster-kit for seamless flush appearance',
),
'led' =>
array (
'title' => 'LED',
'items' => 'LED50 ONE',
),
'cct' =>
array (
'title' => 'CCT',
'items' => '90 CRI 4000K',
),
'beam-angle' =>
array (
'title' => 'Beam Angle',
'items' => '38°',
),
'protocol' =>
array (
'title' => 'Protocol',
'items' => 'Bluetooth',
),
'louvre-lens' =>
array (
'title' => 'Louvre/Lens',
'items' => 'Heavy Spread Lens',
),
)
Any thoughts?
Based on the preferred data structure you specified:
$result = array();
foreach ($page->products_codes as $option) {
$result[$option->parent->name]["title"] = $option->parent->title;
$result[$option->parent->name]["items"][] = $option;
}
$result = array_values($result);
Here's a working example: https://3v4l.org/u9XBk

Replace key in array, with keeping order intact

I would like to replace keys in arrays, because I will move them on two indexes up.
Problem that I am facing is that those are containing same names which will not be ok, if i want to move them up.
This is how array looks like.
$list = array(
'ind' => array(
'messagetype' => 'Alert',
'visibility' => 'Public',
'info' => array(
0 => array(
'urgency' => 'Urgent',
'params' => array(
0 => array(
'Name' => 'display',
'value' => '3; top',
),
1 => array(
'Name' => 'level',
'value' => '1; blue',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GSSD154',
),
),
),
),
1 => array(
'messagetype' => 'Information',
'visibility' => 'Private',
'info' => array(
0 => array(
'urgency' => 'Minor',
'params' => array(
0 => array(
'Name' => 'display',
'value' => '1; left',
),
1 => array(
'Name' => 'level',
'value' => '1; red',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GBECS23',
),
),
),
),
),
),
),
),
);
and this is how I would like the output to be with changing keys in Name0, Name1, which are inside params.
$list = array(
'ind' => array(
'messagetype' => 'Alert',
'visibility' => 'Public',
'info' => array(
0 => array(
'urgency' => 'Urgent',
'params' => array(
0 => array(
'Name0' => 'display',
'value0' => '3; top',
),
1 => array(
'Name1' => 'level',
'value1' => '1; blue',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GSSD154',
),
),
),
),
1 => array(
'messagetype' => 'Information',
'visibility' => 'Private',
'info' => array(
0 => array(
'urgency' => 'Minor',
'params' => array(
0 => array(
'Name0' => 'display',
'value0' => '1; left',
),
1 => array(
'Name1' => 'level',
'value1' => '1; red',
),
),
'area' => array(
'ard' => 'Bob',
'code' => array(
0 => array(
'Name' => 'Badge',
'value' => 'GBECS23',
),
),
),
),
),
),
),
),
);
I have tried with a lots of examples over this website, but could not find one to achieve this.
Code that I used from
How to replace key in multidimensional array and maintain order
function replaceKey($subject, $newKey, $oldKey) {
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($subject)) {
return $subject;
}
$newArray = array(); // empty array to hold copy of subject
foreach ($subject as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$newArray[$key] = replaceKey($value, $newKey, $oldKey);
}
return $newArray;
}
$s = replaceKey($list, 'Name0', 'Name');
print "<PRE>";
print_r($s);
at the moment I get this output:
[0] => Array
(
[Name0] => display
[value] => 1; left
)
[1] => Array
(
[Name0] => level
[value] => 1; red
)
any help would be appreciated. regards
A very strange question, but why not?
The following function returns nothing (a procedure) and changes the array in-place using references but feel free to rewrite it as a "real" function (without references and with a return statement somewhere).
The idea consists to search for arrays, with numeric keys and at least 2 items, in which each item has the Name and value keys. In other words, this approach doesn't care about paths where the targets are supposed to be:
function replaceKeys(&$arr) {
foreach ($arr as &$v) {
if ( !is_array($v) )
continue;
$keys = array_keys($v);
if ( count($keys) < 2 ||
$keys !== array_flip($keys) ||
array_keys(array_merge(...$v)) !== ['Name', 'value'] ) {
replaceKeys($v);
continue;
}
foreach ($v as $k => &$item) {
$item = array_combine(["Name$k", "value$k"], $item);
}
}
}
replaceKeys($list);
print_r($list);
demo

Using array_search for multi value search

$array_subjected_to_search =array(
array(
'name' => 'flash',
'type' => 'hero'
),
array(
'name' => 'zoom',
'type' => 'villian'
),
array(
'name' => 'snart',
'type' => 'antihero'
),
array(
'name' => 'flash',
'type' => 'camera'
)
);
$key = array_search('flash', array_column($array_subjected_to_search, 'name'));
var_dump($array_subjected_to_search[$key]);
This works fine, but is there a way to search using multiple values: eg. get key where name='flash' && type='camera' ?
is there a way to search using multiple values: eg. get key where
name='flash' && type='camera' ?
Simply with array_keys function:
$result_key = array_keys($array_subjected_to_search, [ 'type' => 'camera','name' => 'flash']);
print_r($result_key);
The output:
Array
(
[0] => 3
)
The array_search function accepts an array as parameters the following will work for the use case you provided.
$array_subjected_to_search =array(
array(
'name' => 'flash',
'type' => 'hero'
),
array(
'name' => 'zoom',
'type' => 'villian'
),
array(
'name' => 'snart',
'type' => 'antihero'
),
array(
'name' => 'flash',
'type' => 'camera'
)
);
$compare = array(
'name'=>'flash',
'type'=>'camera'
);
$key = array_search($compare, $haystack);
var_dump($haystack[$key]);
Note: your current search will not function correctly it will always return the zero index because the array_search returns 0 or false.
$key = array_search('flash', array_column($array_subjected_to_search, 'name'));
var_dump($array_subjected_to_search[$key]);
I think I would just make my own function using a loop that will just retrieve the array I want based on either one or two parameters.
function getValueMatch($array, $val1, $val2 = false, $type = 'name')
{
foreach($array as $key => $row) {
# See note below, but it might be handy to have a reversible key name
if($row[$type] == $val1) {
if($val2) {
# You can put a changeable key name to reverse-find
# It might be helpful to search for the other key first
# at some point, best to keep your options open!
$altVar = ($type == 'name')? 'type' : 'name';
if($row[$altVar] == $val2)
return $row;
}
else
return $row;
}
}
}
$array =array(
array(
'name' => 'flash',
'type' => 'hero'
),
array(
'name' => 'zoom',
'type' => 'villian'
),
array(
'name' => 'snart',
'type' => 'antihero'
),
array(
'name' => 'flash',
'type' => 'camera'
)
);
print_r(getValueMatch($array,'flash','camera'));
Gives you:
Array
(
[name] => flash
[type] => camera
)
Example of reverse match (type instead of name):
print_r(getValueMatch($array,'antihero',false,'type'));
Gives you:
Array
(
[name] => snart
[type] => antihero
)

Remove Child Array If Value of A Key is Duplicate

I want to remove a child array from a multi-dimensional array in case a duplicate value found for a particular key. The answer(s) here didn't work at all. The answer here works, however, for large amount of arrays, that gets pretty slower. Looking for a cleaner and faster solution.
Example PHP Array
$args = array();
$args[] = array(
'section' => array(
'id' => 'section1',
'name' => 'Section 1',
),
'name' => 'Shortcode Name',
'action' => 'shortcodeaction',
'icon' => 'codeicon',
'image' => 'codeimage',
);
$args[] = array(
'section' => array(
'id' => 'section2',
'name' => 'Section 2',
),
'name' => 'Shortcode2 Name',
'action' => 'shortcodeaction2',
'icon' => 'codeicon2',
'image' => 'codeimage2',
);
$args[] = array(
'section' => array(
'id' => 'section3',
'name' => 'Section 3',
),
'name' => 'Shortcode3 Name',
'action' => 'shortcodeaction3',
'icon' => 'codeicon3',
'image' => 'codeimage3',
);
$args[] = array(
'section' => array(
'id' => 'section1',
'name' => 'Section 4',
),
'name' => 'Shortcode4 Name',
'action' => 'shortcodeaction4',
'icon' => 'codeicon4',
'image' => 'codeimage4',
);
$args[] = array(
'section' => array(
'id' => 'section5',
'name' => 'Section 5',
),
'name' => 'Shortcode5 Name',
'action' => 'shortcodeaction5',
'icon' => 'codeicon5',
'image' => 'codeimage5',
);
$sections = array();
foreach ( $args as $arg ) {
$sections[] = $arg['section'];
}
And, the print_r($sections) result.
Array
(
[0] => Array
(
[id] => section1
[name] => Section 1
)
[1] => Array
(
[id] => section2
[name] => Section 2
)
[2] => Array
(
[id] => section3
[name] => Section 3
)
[3] => Array
(
[id] => section1
[name] => Section 4
)
[4] => Array
(
[id] => section5
[name] => Section 5
)
)
Both Array[0] and Array[3] has the same value for the key id, therefor the entire Array[3] has to be removed in my case to avoid duplicates.
This is working for me though, but it gets really slow when there are 100s or more arrays.
$knownIds = array();
foreach( $sections AS $key=>$item ) {
if( array_key_exists($item['id'], $knownIds) === true ) {
unset( $sections[$key] );
} else {
$knownIds[$item['id']] = $key;
}
}
$sections = array_values($sections);
Tried several answers here in StackOverflow (including this), but none of them helped in my case.
Thanks
You can modify the whole using array_column and array_filter -
//get all the sections value
$section = array_column($args, 'section');
//store ids in temp array
$idArray = array_unique(array_column($section, 'id'));
//filter the array having unique id
$uniqueSections = array_filter($section, function ($key, $value) use ($idArray) {
return in_array($value, array_keys($idArray));
}, ARRAY_FILTER_USE_BOTH);
var_dump($uniqueSections);
For PHP <5.5
$section = array_map(function($args) {
return $args['section'];
}, $args);
$idArray = array_unique(array_map(function($section){return $section['id'];}, $section));

PHP - structure multidimensional array depending on values

I have an array:
$initialarray = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
2 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
),
3 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
4 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
);
What would be the best way to structure it (to group the resulting sub-arrays) depending first on the 'unit' field's values, and then depending on the 'class' field's values, like so:
$resultarray = array(
// array of all the sub-arrays of 'unit' = 1
$unit[1] = array(
// array of all the sub-arrays of 'unit' = 1 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
)
)
// array of all the sub-arrays of 'unit' = 1 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
)
)
)
// array of all the sub-arrays of 'unit' = 2
$unit[2] = array(
// array of all the sub-arrays of 'unit' = 2 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
)
// array of all the sub-arrays of 'unit' = 2 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
)
)
)
I have asked a similar question here and got a working answer for only one iteration, i.e. for only structuring the array by one of the fields. But I could not make the same solution work for multiple iterations, i.e. for more than one field.
Also, is there a solution to structure a multidimensional array depending on more than two fields?
I think it's not a way of asking the question. It is very simple , you can do this by playing with arrays,keys and etc.... So first you should try hard for the problem. After If you have any problem in the middle of your tries then you can ask that here. I have solved your problem here is the complete code , but next time please do some work and then only post the problem. Never ask for the code.
foreach ($initialarray as $key1=>$val1)
{
foreach ($val1 as $key2=>$val2)
{
if($key2=='unit')
{
$num=$val2;
if($val2!=$num)
$testarr['unit'.$val2]=array();
}
if($key2=='class')
{
$testarr['unit'.$num]['class'.$val2][]=$val1;
}
}
}
print_r($testarr);
I must offer a better way for you and future researchers...
You only need one loop, and you merely need to nominate the result array's key values before using [] to "push" new data into the deepest subarray.
*there is absolutely no need for any condition statements or a second loop.
Code: (Demo)
$initialarray = [
['unit' => 1, 'class' => 1, 'value' => 'string1'],
['unit' => 1, 'class' => 2, 'value' => 'string2'],
['unit' => 1, 'class' => 2, 'value' => 'string3'],
['unit' => 2, 'class' => 1, 'value' => 'string4'],
['unit' => 2, 'class' => 2, 'value' => 'string5']
];
foreach ($initialarray as $row) {
$result[$row['unit']][$row['class']][] = $row;
}
var_export($result);
Output:
array (
1 =>
array (
1 =>
array (
0 =>
array (
'unit' => 1,
'class' => 1,
'value' => 'string1',
),
),
2 =>
array (
0 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string2',
),
1 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string3',
),
),
),
2 =>
array (
1 =>
array (
0 =>
array (
'unit' => 2,
'class' => 1,
'value' => 'string4',
),
),
2 =>
array (
0 =>
array (
'unit' => 2,
'class' => 2,
'value' => 'string5',
),
),
),
)
If I may express myself in the following manner: I only see the front-end of your problem and know nothing about its back-end, e.g. "Where does the data come from?", "How is it collected and stored", etc. so my answer might not be a real help but still I'll give my "tuppence".
If you can store all that data in a relational database (in form of table(s)) it would be much more easier and faster(!) to select the needed data from the database instead of rearranging arrays, which will take some more time in comparison.
Just as an example you might then select (and store it into an array) all items which have unit = '1' and / or all items which have class = '2'. That would make life much more easier IMHO, than having all the data in a multidimensional array and then try to sort it / rearrange it. Especially if you do that based on more than one property.

Categories