I need to build a map of all possibilities from multidimentional array in the following format:
$level['A1']['E1'] = true;
$level['E1']['A1'] = true;
$level['A1']['L1'] = true;
$level['L1']['A1'] = true;
$level['A1']['E2'] = true;
$level['E2']['A1'] = true;
$level['E1']['L1'] = true;
$level['L1']['E1'] = true;
$level['E1']['E2'] = true;
$level['E2']['E1'] = true;
Result needs to have all possible maps in another multidimentional array from A1 to A1, such as:
$level_maps['A1']['E1']['L1']['A1'] = true;
$level_maps['A1']['E1']['E2']['A1'] = true;
$level_maps['A1']['L1']['E1']['A1'] = true;
$level_maps['A1']['L1']['E1']['E2']['A1'] = true;
$level_maps['A1']['E2']['E1']['A1'] = true;
$level_maps['A1']['E2']['E1']['L1']['A1'] = true;
Initial array can be much bigger and I'm having a hard time with a recursive function.
Edit:
I have a simple class with the following function:
private function buildMap(array $levels, $parent) {
$map = array();
foreach ($levels as $level1 => $level2_vals) {
foreach($level2_vals as $level2 => $val) {
if ($parent == $level1) {
$map[$level2] = true;
unset($levels[$level1][$level2]);
$level3 = $this->buildMap($levels, $level2);
if(!empty($level3) && $level2 != $this->end_level) {
$map[$level2] = $level3;
}
else if($level2 != $this->end_level) {
$map[$level2] = false;
}
}
}
}
return $map;
}
calling it with:
$map[$this->start_level] = $this->buildMap($level, $this->start_level);
but it does not work correctly, especially on bigger sets of levels.
Sorry if I am unclear, was just looking for a recursive function example to start with.
Here how it work check the example bellow :
<?php
$level['A1']['E1'] = true;
$level['E1']['A1'] = true;
$level['A1']['L1'] = true;
$level['L1']['A1'] = true;
$level['A1']['E2'] = true;
$level['E2']['A1'] = true;
$level['E1']['L1'] = true;
$level['L1']['E1'] = true;
$level['E1']['E2'] = true;
$level['E2']['E1'] = true;
/// generate array key
$array_keys=array();
foreach($level as $key1 =>$values)
{
foreach($values as $key2 => $values2)
{
$array_keys[]=$key1.'-'.$key2;
}
}
/// split array parent and childrent on diffrent parts
$parent='A1';
$parent_keys=array();
$children_keys=array();
foreach($level as $key =>$val)
{
foreach($val as $key2 =>$val2)
{
if($key == $parent)
$parent_keys[$key.'-'.$key2]=true;
else
$children_keys[$key.'-'.$key2]=true;
}
}
$last_array=array();
foreach($parent_keys as $key =>$va)
{
$exp=explode('-',$key);
foreach($children_keys as $key2 =>$va2)
{
$arrunique=array();
if(!strchr($key2,$exp[1])){
$exp2=explode('-',$key2);
foreach($exp as $r)
{
$arrunique[$r]=$r;
}
foreach($exp2 as $r)
{
$arrunique[$r]=$r;
}
if(in_array($exp[1].'-'.$exp2[0],$array_keys))
$last_array[implode('-',$arrunique).'-'.$exp[0]]=true;
}
}
}
foreach($last_array as $key=>$va)
{
print $key."\n";
}
You can execute from sandbox : LINK
Related
It seems that I can only read the value from a variable I pass in use($ids) but I can't update the value. How can I change the value?
here is my code
public function show(LPJ $lpj){
$ids = [];
$lpj->request->each(function ($item, $key) use ($ids) {
if ($item->is_submitted) {
return true;
}
if (!$item->form) {
return true;
}
$form = json_decode($item->form, true);
$is_submitted = false;
foreach ($form as $value) {
if (!$value['required']) {
continue;
}
if ($value['value'] === null) {
$is_submitted = false;
break;
}
$is_submitted = true;
}
if ($is_submitted) {
$request_lpj = RequestLPJ::find($item->id);
$request_lpj->is_submitted = true;
$request_lpj->save();
// here I tried to update the $ids
$ids[] = $key;
}
});
}
And it always return an empty array.
How can I pass value to the parent variable?
Thank you
Try Passing by Reference use (&$ids)
$ids = [];
$lpj->request->each(function ($item, $key) use (&$ids) {
if ($item->is_submitted) {
return true;
}
if (!$item->form) {
return true;
}
$form = json_decode($item->form, true);
$is_submitted = false;
foreach ($form as $value) {
if (!$value['required']) {
continue;
}
if ($value['value'] === null) {
$is_submitted = false;
break;
}
$is_submitted = true;
}
if ($is_submitted) {
$request_lpj = RequestLPJ::find($item->id);
$request_lpj->is_submitted = true;
$request_lpj->save();
// here I tried to update the $ids
$ids[] = $key;
}
});
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
From that array basically I need to create a function with the array value parameter and then it gives me the array keys.
For example:
find_index('Cat');
Output :
The result is animal, 1
You could probably do something like
function find_index($value) {
foreach ($arr as $index => $index2) {
$exists = array_search($value, $index2);
if ($exists !== false) {
echo "The result is {$index}, {$exists}";
return true;
}
}
return false;
}
Try this:
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
function find_index($searchVal, $arr){
return array_search($searchVal, $arr);
}
print_r(find_index('Cat', $arr['animal']));
Consider this Array,
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
Here is Iterator Method,
$search = 'InsectSub1';
$matches = [];
$arr_array = new RecursiveArrayIterator($arr);
$arr_array_iterator = new RecursiveIteratorIterator($arr_array);
foreach($arr_array_iterator as $key => $value)
{
if($value === $search)
{
$fill = [];
$fill['category'] = $arr_array->key();
$fill['key'] = $arr_array_iterator->key();
$fill['value'] = $value;
$matches[] = $fill;
}
}
if($matches)
{
// One or more Match(es) Found
}
else
{
// Not Found
}
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
$search_for = 'Cat';
$search_result = [];
while ($part = each($arr)) {
$found = array_search($search_for, $part['value']);
if(is_int($found)) {
$fill = [ 'key1' => $part['key'], 'key2' => $found ];
$search_result[] = $fill;
}
}
echo 'Found '.count($search_result).' result(s)';
print_r($search_result);
Having some issues parsing my multidimensional php array and removing duplicates. I've spent a good four hours trying to figure out what I'm doing wrong with no luck. If someone could help me out that would wonderful.
Format of multidimensional array:
Array(Array("id"=>?, "step_num"=>?, "desc"=>?))
Example data set:
Array(
[0]=> Array([id]=>1, [step_count]=>1, [desc]=>"Something"),
[1]=> Array([id]=>2, [step_count]=>1, [desc]=>"Something New"),
[2]=> Array([id]=>3, [step_count]=>1, [desc]=>"Something Newest")
)
Here's how I am trying to only have the step_count with the most recent desc by comparing id values: ($subStepsFound has the same format as the above array and $results is an empty array to begin with)
foreach($subStepsFound AS $step){
$found = false;
$removeEntry = false;
$index = 0;
foreach($results AS $key=>$result){
if($step['step_count'] == $result['step_count']){
$found = true;
if($step['id'] > $result['id']){
$removeEntry = true;
}
}
if($removeEntry === true){
$index = $key;
}
}
if($removeEntry === true){
//unset($results[$index]);
$results[$index] = $step;
}
if($found === false){
$results[] = $step;
}
}
Expected output of the resulting array:
Array(
[0]=> Array([id]=>4, [step_count]=>1, [desc]=>"Something Newest")
)
See 1., 2., 3. in comments:
foreach($subStepsFound AS $step){
$found = false;
$removeEntry = false;
$index = 0;
foreach($results AS $key=>$result){
if($step['step_count'] == $result['step_count']){
$found = true;
if($step['id'] > $result['id']){
$removeEntry = true;
}
}
if($removeEntry === true){
$results[$key] = $step; // 2. UP TO HERE
$removeEntry = false; // 3. RESET $removeEntry
}
}
/*
if($removeEntry === true){
//unset($results[$index]);
$results[$index] = $step; // 1. MOVE THIS...
}
*/
if($found === false){
$results[] = $step;
}
}
print_r($results);
Online example: http://sandbox.onlinephpfunctions.com/code/1db78a8c08cbee9d04fe1ca47a6ea359cacdd9e9
/*super_unique: Removes the duplicate sub-steps found*/
function super_unique($array,$key){
$temp_array = array();
foreach ($array as &$v) {
if (!isset($temp_array[$v[$key]])) $temp_array[$v[$key]] =& $v;
}
$array = array_values($temp_array);
return $array;
}
$results = super_unique($subStepsFound, 'step_count');
I have two arrays like
$a1= array(
array('a'=>1,'b'=>2, 'c'=>3), // similar to $a2[0]
array('a'=>3,'b'=>4, 'c'=>5), // similar to $a2[1]
array('a'=>9,'b'=>6, 'c'=>9)
);
$a2= array(
array('a'=>1,'b'=>2, 'c'=>3),
array('a'=>3,'b'=>4, 'c'=>5),
array('a'=>5,'b'=>6, 'c'=>7),
array('a'=>11,'b'=>4, 'c'=>13),
array('a'=>14,'b'=>6, 'c'=>3)
);
I want a resulting array that does't have common values like
$arrayResult= array(
array('a'=>9,'b'=>6, 'c'=>9),// from $a1[3]
array('a'=>5,'b'=>6, 'c'=>7),// from $a2[2]
array('a'=>11,'b'=>4, 'c'=>13),// from $a2[3]
array('a'=>14,'b'=>6, 'c'=>3)// from $a2[4]
);
I have tried array_udiff, and also separate function but I'm unable to get the right thing.
Hmm fast solution, not optimized
$result = array();
foreach($a1 as $va1) {
$found = false;
foreach($a2 as $va2) {
$x = array_diff($va1, $va2);
if (empty($x)) {
$found = true;
}
}
if (!$found) {
$result[] = $va1;
}
}
foreach($a2 as $va2) {
$found = false;
foreach($a1 as $va1) {
$x = array_diff($va2, $va1);
if (empty($x)) {
$found = true;
}
}
if (!$found) {
$result[] = $va2;
}
}
var_dump($result);
EDIT: A little optimized (unseting values that were found before):
$a1= array(
array('a'=>1,'b'=>2, 'c'=>3), // similar to $a2[0]
array('a'=>3,'b'=>4, 'c'=>5), // similar to $a2[1]
array('a'=>9,'b'=>6, 'c'=>9)
);
$a2= array(
array('a'=>1,'b'=>2, 'c'=>3),
array('a'=>3,'b'=>4, 'c'=>5),
array('a'=>5,'b'=>6, 'c'=>7),
array('a'=>11,'b'=>4, 'c'=>13),
array('a'=>14,'b'=>6, 'c'=>3)
);
$i=0;
$result = array();
foreach($a1 as $ka1 => $va1) {
$found = false;
foreach($a2 as $ka2 => $va2) {
$i++;
$x = array_diff($va1, $va2);
if (empty($x)) {
$found = true;
unset($a2[$ka2], $a1[$ka1]);
}
}
if (!$found) {
$result[] = $va1;
}
}
foreach($a2 as $ka2 => $va2) {
$found = false;
foreach($a1 as $ka1 => $va1) {
$i++;
$x = array_diff($va2, $va1);
if (empty($x)) {
unset($a2[$ka2], $a1[$ka1]);
$found = true;
}
}
if (!$found) {
$result[] = $va2;
}
}
var_dump($result);echo $i;
function check_diff_multi($array1, $array2){
$result = array();
foreach($array1 as $key => $val) {
if(isset($array2[$key])){
if(is_array($val) && is_array($array2[$key])){
$result[$key] = check_diff_multi($val, $array2[$key]);
}
} else {
$result[$key] = $val;
}
}
return $result;
}
//call this function
check_diff_multi($a1,$a2);
I want to remove some duplicate values on an array, but there is a condition that the script has to ignore the array that contains a specific word.
Below code is adapted from PHP: in_array.
$array = array( 'STK0000100001',
'STK0000100002',
'STK0000100001', //--> This should be remove
'STK0000100001-XXXX', //--> This should be ignored
'STK0000100001-XXXX' ); //--> This should be ignored
$ignore_values = array('-XXXX');
if(make_unique($array, $ignore_values) > 0) {
//ERROR HERE
}
The function to make the array unique is:
function make_unique($array, $ignore) {
$i = 0;
while($values = each($array)) {
if(!in_array($values[1], $ignore)) {
$dupes = array_keys($array, $values[1]);
unset($dupes[0]);
foreach($dupes as $rmv) {
$i++;
}
}
}
return $i;
}
I have tried to use if(!in_array(str_split($values[1]), $ignore)) ... but it just the same.
The array should become like:
STK0000100001
STK0000100002
STK0000100001-XXXX
STK0000100001-XXXX
How to do that?
Try this one, just remove the print_r(); inside the function when using in production
if(make_unique($array, $ignore_values) > 0) {
//ERROR HERE
}
function make_unique($array, $ignore) {
$array_hold = $array;
$ignore_val = array();
$i = 0;
foreach($array as $arr) {
foreach($ignore as $ign) {
if(strpos($arr, $ign)) {
array_push( $ignore_val, $arr);
unset($array_hold[$i]);
break;
}
}
$i++;
}
$unique_one = (array_unique($array_hold));
$unique_one = array_merge($unique_one,$ignore_val);
print_r($unique_one);
return count($array) - count($unique_one);
}
This should work for >= PHP 5.3.
$res = array_reduce($array, function ($res, $val) use ($ignore_values) {
$can_ignore = false;
foreach ($ignore_values as $ignore_val) {
if (substr($val, 0 - strlen($ignore_val)) == $ignore_val) {
$can_ignore = true;
break;
}
}
if ( $can_ignore || ! in_array($val, $res)) {
$res[] = $val;
}
return $res;
}, array()
);
Otherwise
$num_of_duplicates = 0;
$res = array();
foreach ($array as $val) {
$can_ignore = false;
foreach ($ignore_values as $ignore_val) {
if (substr($val, 0 - strlen($ignore_val)) == $ignore_val) {
$num_of_duplicates++;
$can_ignore = true;
break;
}
}
if ( $can_ignore || ! in_array($val, $res)) {
$res[] = $val;
}
}
Edit: Added duplicate count to the second snippet.