I have two arrays with same amount of values. I need to combine them ( array1 value to key, array2 value as value) without losing the values of the second array due to duplicate key. when I use combine_array() as expected it just gets the last value of the second array with the same key.
Array
(
[0] => 1
[1] => 2
[2] => 2
[3] => 3
)
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Desired result
Array
(
[1] => 1
[2] => Array(
[0]=>2
[1]=>3
)
[3] => 2
)
This code will meet your request
$array1 = array("0"=>1,"1"=>2,"2"=>2,"3"=>3);
$array2 = array("0"=>1,"1"=>2,"2"=>3,"3"=>4);
$array = array();
foreach($array1 as $key => $value){
if($value != $array2[$key]){
$array[$key][] = $value;
$array[$key][] = $array2[$key];
}else{
$array[$key] = $value;
}
}
print_r($array);
The desired result is
Array
(
[0] => 1
[1] => 2
[2] => Array
(
[0] => 2
[1] => 3
)
[3] => Array
(
[0] => 3
[1] => 4
)
)
I'm sure there are way better solutions than this, but it does the job for now. I would appreciate if someone can send a better written solution.
$combined = array();
$tempAr = array();
$firstMatch = array();
$count = 0;
foreach ($array1 as $index => $key) {
if (array_key_exists($key, $combined)) {
$tempAr[] = $array2[$index];
$count++;
} else {
$totalCount = $count;
}
if (!array_key_exists($key, $firstMatch)) {
$firstMatch[$key] = $array2[$index];
}
$output = array_slice($tempAr, $totalCount);
$combined[$key] = $output;
}
$combined = array_merge_recursive($firstMatch, $combined);
Problem
Need to find the all nearby node elements for every node on the following graph using PHP
Graph
Input String
$string_arr = array (‘c1#c2#6’, ‘c2#c3#12’, ‘c2#c4#3’, ‘c3#c5#22’, ‘c3#c6#23’, ‘c4#c7#13’, ‘c5#c8#16’, ‘c6#c8#11’, ‘c6#c9#9’, ‘c7#c9#12’, ‘c9#c10#15’, ‘c8#c10#7’);
(Use above variable as input parameter for your code. And you can treat it as string or array or array of string)
Required OUTPUT:
Please print the array showing all node elements with their nearby node.
e.g.
Array(
[c1] => Array
(
[0] => c2
)
[c2] => Array
(
[0] => c1
[1] => c3
[2] => c4
)
)
My Code
<?php
$string_arr = array('c1#c2#6', 'c2#c3#12', 'c2#c4#3', 'c3#c5#22', 'c3#c6#23', 'c4#c7#13', 'c5#c8#16', 'c6#c8#11', 'c6#c9#9',
'c7#c9#12', 'c9#c10#15', 'c8#c10#7');
foreach ($string_arr as $k => $v) {
$tmp = explode('#', $v);
$new_array[$tmp[0]][] = $tmp[1];
#$new_array2[$tmp[0]][] = $tmp[2];
}
print_r($new_array);
?>
My Output
Array (
[c1] => Array
(
[0] => c2
)
[c2] => Array
(
[0] => c3
[1] => c4
)
[c3] => Array
(
[0] => c5
[1] => c6
)
[c4] => Array
(
[0] => c7
)
[c5] => Array
(
[0] => c8
)
[c6] => Array
(
[0] => c8
[1] => c9
)
[c7] => Array
(
[0] => c9
)
[c9] => Array
(
[0] => c10
)
[c8] => Array
(
[0] => c10
)
)
I think all you need to do is also add the items in the other way round, so you currently add...
$new_array[$tmp[0]][] = $tmp[1];
so also add with the values swapped
$new_array[$tmp[1]][] = $tmp[0];
To give...
foreach ($string_arr as $k => $v) {
$tmp = explode('#', $v);
$new_array[$tmp[0]][] = $tmp[1];
$new_array[$tmp[1]][] = $tmp[0];
}
<?php
$string_arr = array ('c1#c2#6', 'c2#c3#12', 'c2#c4#3', 'c3#c5#22', 'c3#c6#23', 'c4#c7#13', 'c5#c8#16', 'c6#c8#11', 'c6#c9#9', 'c7#c9#12', 'c9#c10#15', 'c8#c10#7');
$simplifyArr = array();
foreach ($string_arr as $key => $value) {
$simplifyArr[] = getnode($value);
}
$keysArr = array_unique(array_column($simplifyArr, 'parent'));
$outputArr = array();
foreach ($keysArr as $key) {
foreach ($simplifyArr as $value) {
if($value['parent'] == $key){
$outputArr[$key][] = $value['child'];
}
if($value['child'] == $key){
$outputArr[$key][] = $value['parent'];
}
}
}
echo "<pre>";
print_r($outputArr);
echo "</pre>";
function getnode($string)
{
$extract = explode('#', $string);
$arr['parent'] = $extract[0];
$arr['child'] = $extract[1];
$arr['weight'] = $extract[2];
return $arr;
}
?>
I am trying to sort an array to ensure that the parent of any item always exists before it in the array. For example:
Array
(
[0] => Array
(
[0] => 207306
[1] => Bob
[2] =>
)
[1] => Array
(
[0] => 199730
[1] => Sam
[2] => 199714
)
[2] => Array
(
[0] => 199728
[1] => Simon
[2] => 207306
)
[3] => Array
(
[0] => 199714
[1] => John
[2] => 207306
)
[4] => Array
(
[0] => 199716
[1] => Tom
[2] => 199718
)
[5] => Array
(
[0] => 199718
[1] => Phillip
[2] => 207306
)
[6] => Array
(
[0] => 199720
[1] => James
[2] => 207306
)
)
In the above array this "fails" as [1][2] (Sam) does not yet exist and nor does [4][2] (Tom).
The correct output would be as, in this case, as both Sam and Tom's parents already exist before they appear in the array:
Array
(
[0] => Array
(
[0] => 207306
[1] => Bob
[2] =>
)
[1] => Array
(
[0] => 199714
[1] => John
[2] => 207306
)
[2] => Array
(
[0] => 199730
[1] => Sam
[2] => 199714
)
[3] => Array
(
[0] => 199728
[1] => Simon
[2] => 207306
)
[4] => Array
(
[0] => 199718
[1] => Phillip
[2] => 207306
)
[5] => Array
(
[0] => 199716
[1] => Tom
[2] => 199718
)
[6] => Array
(
[0] => 199720
[1] => James
[2] => 207306
)
)
I found an answer https://stackoverflow.com/a/12961400/1278201 which was very close but it only seems to go one level deep (i.e. there is only ever one parent) whereas in my case there could be 1 or 10 levels deep in the hierarchy.
How do I sort the array so no value can appear unless its parent already exists before it?
This will trivially order the array (in O(n)) putting first all those with no parent, then these whose parent is already in the array, iteratively, until there's no children having the current element as parent.
# map the children by parent
$parents = ['' => []];
foreach ($array as $val) {
$parents[$val[2]][] = $val;
}
# start with those with no parent
$sorted = $parents[''];
# add the children the current nodes are parent of until the array is empty
foreach ($sorted as &$val) {
if (isset($parents[$val[0]])) {
foreach ($parents[$val[0]] as $next) {
$sorted[] = $next;
}
}
}
This code requires PHP 7, it may not work in some cases under PHP 5. - for PHP 5 compatibility you will have to swap the foreach ($sorted as &$val) with for ($val = reset($sorted); $val; $val = next($sorted)):
# a bit slower loop which works in all versions
for ($val = reset($sorted); $val; $val = next($sorted)) {
if (isset($parents[$val[0]])) {
foreach ($parents[$val[0]] as $next) {
$sorted[] = $next;
}
}
}
Live demo: https://3v4l.org/Uk6Gs
I have two different version for you.
a) Using a "walk the tree" approach with recursion and references to minimize memory consumption
$data = [
[207306,'Bob',''], [199730,'Sam',199714],
[199728,'Simon',207306], [199714,'John',207306],
[199716, 'Tom',199718], [199718,'Phillip',207306],
[199720,'James',207306]
];
$list = [];
generateList($data, '', $list);
var_dump($list);
function generateList($data, $id, &$list) {
foreach($data as $d) {
if($d[2] == $id) {
$list[] = $d; // Child found, add it to list
generateList($data, $d[0], $list); // Now search for childs of this child
}
}
}
b) Using phps built in uusort()function (seems only to work up to php 5.x and not with php7+)
$data = [
[207306,'Bob',''], [199730,'Sam',199714],
[199728,'Simon',207306], [199714,'John',207306],
[199716, 'Tom',199718], [199718,'Phillip',207306],
[199720,'James',207306]
];
usort($data, 'cmp');
var_dump($data);
function cmp($a, $b) {
if($a[2] == '' || $a[0] == $b[2]) return -1; //$a is root element or $b is child of $a
if($b[2] == '' || $b[0] == $a[2]) return 1; //$b is root element or $a is child of $b
return 0; // both elements have no direct relation
}
I checked this works in PHP 5.6 and PHP 7
Sample array:
$array = Array(0 => Array(
0 => 207306,
1 => 'Bob',
2 => '',
),
1 => Array
(
0 => 199730,
1 => 'Sam',
2 => 199714,
),
2 => Array
(
0 => 199728,
1 => 'Simon',
2 => 207306,
),
3 => Array
(
0 => 199714,
1 => 'John',
2 => 207306,
),
4 => Array
(
0 => 199716,
1 => 'Tom',
2 => 199718,
),
5 => Array
(
0 => 199718,
1 => 'Phillip',
2 => 207306,
),
6 => Array
(
0 => 199720,
1 => 'James',
2 => 207306,
),
);
echo "<pre>";
$emp = array();
//form the array with parent and child
foreach ($array as $val) {
$manager = ($val[2] == '') ? 0 : $val[2];
$exist = array_search_key($val[2], $emp);
if ($exist)
$emp[$exist[0]][$val[0]] = $val;
else
//print_R(array_search_key(199714,$emp));
$emp[$manager][$val[0]] = $val;
}
$u_emp = $emp[0];
unset($emp[0]);
//associate the correct child/emp after the manager
foreach ($emp as $k => $val) {
$exist = array_search_key($k, $u_emp);
$pos = array_search($k, array_keys($u_emp));
$u_emp = array_slice($u_emp, 0, $pos+1, true) +
$val +
array_slice($u_emp, $pos-1, count($u_emp) - 1, true);
}
print_R($u_emp); //print the final result
// key search function from the array
function array_search_key($needle_key, $array, $parent = array())
{
foreach ($array AS $key => $value) {
$parent = array();
if ($key == $needle_key)
return $parent;
if (is_array($value)) {
array_push($parent, $key);
if (($result = array_search_key($needle_key, $value, $parent)) !== false)
return $parent;
}
}
return false;
}
Find the below code that might be helpful.So, your output is stored in $sortedarray.
$a=array(array(207306,'Bob',''),
array (199730,'Sam',199714),
array(199728,'Simon',207306),
array(199714,'John',207306),
array(199716,'Tom',199718),
array(199718,'Phillip',207306),
array(199720,'James',207306));
$sortedarray=$a;
foreach($a as $key=>$value){
$checkvalue=$value[2];
$checkkey=$key;
foreach($a as $key2=>$value2){
if($key<$key2){
if ($value2[0]===$checkvalue){
$sortedarray[$key]=$value2;
$sortedarray[$key2]=$value;
}else{
}
}
}
}
print_r($sortedarray);
What about this approach:
Create an empty array result.
Loop over your array and only take the items out of it where [2] is empty and insert them into result.
When this Loop is done you use a foreach-Loop inside a while-loop. With the foreach-Loop you take every item out of your array where [2] is already part of result. And you do this as long as your array contains anything.
$result = array();
$result[''] = 'root';
while(!empty($yourArray)){
foreach($yourArray as $i=>$value){
if(isset($result[$value[2]])){
// use the next line only to show old order
$value['oldIndex'] = $i;
$result[$value[0]] = $value;
unset($yourArray[$i]);
}
}
}
unset($result['']);
PS: You may run into trouble by removing parts of an array while walking over it. If you do so ... try to solve this :)
PPS: Think about a break condition if your array have an unsolved loop or a child without an parent.
you can use your array in variable $arr and use this code it will give you required output.
function check($a, $b) {
return ($a[0] == $b[2]) ? -1 : 1;
}
uasort($arr, 'check');
echo '<pre>';
print_r(array_values($arr));
echo '</pre>';
I need to add another another element to each level of the array (sorry, think that is bad terminology).
I have an array -
Array ( [0] => Array (
[actor_rt_id] => 162683283,
[item_number] => 3 )
[1] => Array (
[actor_rt_id] => 162657351,
[item_number] => 5 )
)
This code produces the array. The commented out line is what I tried to add to the array. The code before the comment creates the array.
$data_itemone['actor_rt_id'] = $this->input->post('actor_id');
$data_itemtwo['item_number'] = $this->input->post('item_number');
$data_item = array_merge($data_itemone, $data_itemtwo);
$res = [];
foreach($data_item as $key => $value){
foreach ($value as $data => $thevalue) {
$res[$data][$key] = $thevalue;
//$res['film_id'] = $film_id;
}
}
I have an another variable I need to add from post which is a single string.
$film_id = $this->input->post('film_id');
I need it to be in the array like so -
Array ( [0] => Array (
[actor_rt_id] => 162683283,
[item_number] => 3,
[film_id] => 52352
)
[1] => Array (
[actor_rt_id] => 162657351,
[item_number] => 5,
[film_id] => 52352
)
)
...but my code (uncommented) produces -
Array ( [0] => Array (
[actor_rt_id] => 162683283,
[item_number] => 3
)
[film_id] => 16639,
[1] => Array
( [actor_rt_id] => 162657351,
[item_number] => 5 )
)
Tried a few things. Can't seem to get it to work.
Change
$res['film_id'] = $film_id;
to
$res[$data]['film_id'] = $film_id;
this will add it to the right array.
How if you try this.
$data_itemone['actor_rt_id'] = [123, 245];
$data_itemtwo['item_number'] = [456, 789];
$film_id = 52352;
$data_item = array_merge($data_itemone, $data_itemtwo);
$res = [];
foreach($data_item as $key => $value){
foreach ($value as $data => $thevalue) {
$res[$data][$key] = $thevalue;
$res[$data]['film_id'] = $film_id;
}
}
print_r($res);
Try this one
<?
$data_itemone['actor_rt_id'] = $this->input->post('actor_id');
$data_itemtwo['item_number'] = $this->input->post('item_number');
$film_id = $this->input->post('film_id');
$data_item = array_merge($data_itemone, $data_itemtwo);
$res = [];
foreach($data_item as $key => $value){
foreach ($value as $data => $thevalue) {
$res[$data][$key] = $thevalue;
$res[$data]['film_id'] = $film_id;
}
}
?>
I have an array with float indexes that I'm getting from a plugin. I want to parse this array and take the ones that are float and put them in as a new array. Meaning what I have is
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5.1] => gsurvey5649a964f
[5.2] => gsurvey5fddb5e9f
[5.3] => gsurvey533c5b311
[5.4] => gsurvey5c8933efb
[5.5] => gsurvey5da48f59b
What I want is:
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => array (
[0] => gsurvey5649a964f
[1] => gsurvey5fddb5e9f
[2] => gsurvey533c5b311
[3] => gsurvey5c8933efb
[4] => gsurvey5da48f59b
)
I'm not clear on what's the best way to approach this.
I made the comment above that this problem is very prone to error because it is possible to have input that would set a single value to be both a string and an array at the same time. That will obviously fail. Assuming that the input is clean...
$new_array = array();
foreach($old_array as $key=>$val)
{
$a = explode('.', $key);
if(sizeof($a)==2)
{
if(!isset($new_array[$a[0]])) $new_array[$a[0]] = array();
$new_array[$a[0]][] = $val;
}
else $new_array[$key]=$val;
}
Example with array_walk:
$array = array (
'1' => 'gsurvey128f54af2',
'2' => 'gsurvey282bd4253',
'5.1' => 'gsurvey5649a964f',
'5.2' => 'gsurvey5fddb5e9f',
'5.3' => 'gsurvey533c5b311',
'5.4' => 'gsurvey5c8933efb',
'5.5' => 'gsurvey5da48f59b'
);
$output = array();
array_walk( $array, function( $item, $key ) use ( &$output ) {
$keys = explode( '.', $key );
isset( $keys[1] ) ? $output[ $keys[0] ][ $keys[1] ] = $item : $output[ $keys[0] ] = $item;
});
print_r( $output );
/*
Array
(
[1] => gsurvey128f54af2
[2] => gsurvey282bd4253
[5] => Array
(
[1] => gsurvey5649a964f
[2] => gsurvey5fddb5e9f
[3] => gsurvey533c5b311
[4] => gsurvey5c8933efb
[5] => gsurvey5da48f59b
)
)
*/
For this specific case, this should work:
foreach($array as $k => $v) {
if(count($i = explode('.', $k)) > 1) {
$result[$i[0]][] = $v;
} else {
$result[$k] = $v;
}
}