Change variable value in recursive function - php

Thanks in advance for your help!
I need to change the values from the variable $v_file recursively. For that I created a recursive function that loops through my array $arr and substitutes the placeholders with the values from my array.
function replace_file($arr, $v_file){
foreach ($arr as $key => $value) {
if (is_array($value)) {
replace_file($value, $v_file);
}else{
if($value == "check"){echo("$key ||| $value <br/>");
$v_file = str_replace('{{'.$key.'}}', 'check-square.svg', $v_file);
}elseif ($value == "uncheck") {
$v_file = str_replace('{{'.$key.'}}', 'square.svg', $v_file);
}else{
$v_file = str_replace('{{'.$key.'}}', $value, $v_file);
}
}
}
return $v_file;
}
Here is the array I'm trying to loop through
Array (
[nomec] => john doe
[pessoac] => 1234
[datanascc] => 01/01/0001
[cpfcnpjc] => 999.999.999-99
[rgc] => 99.999.999-9
[proposta] => Array (
[inclusao] => check
[exclusao] => uncheck
[alteracaodados] => uncheck
[segviacartao] => uncheck
)
[beneficiario] => Array (
[titular] => check
[dependente] => uncheck
[agregado] => check
)
)
And this is the info I'm trying to substitute with the values from the array:
$file = "{{nomec}},
{{pessoac}},
{{datanascc}},
{{cpfcnpjc}},
{{rgc}},
{{inclusao}},
{{exclusao}},
{{alteracaodados}},
{{segviacartao}},
{{titular}},
{{dependente}},
{{agregado}}";
When i call the function with replace_file($obj, $file); and print the result, i get:
john doe, 1234, 01/01/0001, 999.999.999-99, 99.999.999-9, {{inclusao}}, {{exclusao}}, {{alteracaodados}}, {{segviacartao}}, {{titular}}, {{dependente}}, {{agregado}}
Can someone help me with this function?
Thanks!

Related

How to show duplicate data in multidimensional array using PHP

I am using Spout Excel reader to read Excel files from php code and saving into a multidimensional array in PHP variable,Array looks like this
$array = [
[
'id[0]' => 'BX-78',
'Name[0]' => 'XXX',
'Address[0]' => 'YUUSATD'
],
[
'id[1]' => 'BX-79',
'Name[1]' => 'YYY',
'Address[1]' => 'DHJSHDJGY'
],
[
'id[2]' => 'BX-80',
'Name[2]' => 'ZZZ',
'Address[2]' => 'DDSDSDA'
]
[
'id[3]' => 'BX-78',
'Name[3]' => 'AAA',
'Address[3]' => 'FSDSDS'
][
'id[4]' => 'BX-81',
'Name[4]' => 'XXX',
'Address[4]' => 'DSDSDSD'
]];
Now i want to show duplicate data from above array using two keys ['id'] and ['name'] if id repeats show as duplicate data,
If name repeats show that row as duplicate data if both are duplicate show as again duplicate row
Otherwise it is unique row.
I have tried using multidimensional array sorting but it is using only one key to match data in rows.
foreach ($arrExcelData as $v) {
if (isset($arrExcelData[$v[0]])) {
// found duplicate
continue;
}
// remember unique item
$arrExcelData3[$v[0]] = $v;
}
// if you need a zero-based array, otheriwse work with $_data
$arrExcelData2 = array_values($arrExcelData3);
Edited : Expected Output Result :
Matching Rows:
Id Name Address
-------------------------
BX-78 XXX YUUSATD
BX-78 AAA DDSDSDA
BX-81 XXX DSDSDSD`
If you want to list the duplicate values, I think the address of the second match should be FSDSDS as there is not item with name AAA and value DDSDSDA:
BX-78 AAA FSDSDS
If that is the case, what you could do is to first use a double foreach to mark the arrays that contain a duplicate id or name by for example adding a property named id and name except when the array is itself in the second loop.
After this loop, you can tell which arrays are the duplicate ones. Instead of using a corresponding index 0 as in id[0], I have used reset and next so it is not tied to these indexes.
To get the filtered result you could use array_reduce to check for the array keys and unset them.
For example:
foreach ($array as $index => $a) {
foreach ($array as $v) {
if ($v === $a) continue;
if (reset($v) === reset($a)) $array[$index]["id"] = "duplicate";
if (next($v) === next($a)) $array[$index]["name"] = "duplicate";
}
}
$array = array_reduce($array, function($carry, $item) {
if (array_key_exists("id", $item) || array_key_exists("name", $item)) {
unset($item["id"], $item["name"]);
$carry[] = $item;
}
return $carry;
}, []);
print_r($array);
Result
Array
(
[0] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
[1] => Array
(
[id[3]] => BX-78
[Name[3]] => AAA
[Address[3]] => FSDSDS
)
[2] => Array
(
[id[4]] => BX-81
[Name[4]] => XXX
[Address[4]] => DSDSDSD
)
)
See a php demo
I've this very pragmatic approach:
$spout_output = [
[
'id[0]' => 'BX-78',
'Name[0]' => 'XXX',
'Address[0]' => 'YUUSATD'
],
[
'id[1]' => 'BX-79',
'Name[1]' => 'YYY',
'Address[1]' => 'DHJSHDJGY'
],
[
'id[2]' => 'BX-80',
'Name[2]' => 'ZZZ',
'Address[2]' => 'DDSDSDA'
],
[
'id[3]' => 'BX-78',
'Name[3]' => 'AAA',
'Address[3]' => 'FSDSDS'
],
[
'id[4]' => 'BX-81',
'Name[4]' => 'XXX',
'Address[4]' => 'DSDSDSD'
]];
// store id to row, and name to row mappings.
// id and name will be keys, value will be an array of indexes of the array $spout_output
$id_to_rows = array();
$name_to_rows = array();
$duplicate_ids = array();
$duplicate_names = array();
foreach($spout_output as $row => $data)
{
$key_id = 'id['.$row.']';
$key_name = 'Name['.$row.']';
if(!isset($data[$key_id]))
continue;
$value_id = $data[$key_id];
$value_name = $data[$key_name];
if(!isset($id_to_rows[$value_id]))
{
$id_to_rows[$value_id] = array();
}
else
{
if(!isset($duplicate_ids[$value_id]))
{
$duplicate_ids[$value_id] = $id_to_rows[$value_id];
}
$duplicate_ids[$value_id][] = $row;
}
if(!isset($name_to_rows[$value_name]))
{
$name_to_rows[$value_name] = array();
}
else
{
if(!isset($duplicate_names[$value_name]))
{
$duplicate_names[$value_name] = $name_to_rows[$value_name];
}
$duplicate_names[$value_name][] = $row;
}
$id_to_rows[$value_id][] = $row;
$name_to_rows[$value_name][] = $row;
}
echo 'Duplicates:';
echo '<br>';
$shown_rows = array();
foreach($duplicate_ids as $id => $rows)
{
foreach($rows as $nr)
{
echo $id . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
echo '<br>';
$shown_rows[] = $nr;
}
}
foreach($duplicate_names as $name => $rows)
{
foreach($rows as $nr)
{
// if already shown above, skip this row
if(in_array($nr, $shown_rows))
continue;
echo $spout_output[$nr]['id['.$nr.']'] . '|' . $spout_output[$nr]['Name['.$nr.']'] . '|' . $spout_output[$nr]['Address['.$nr.']'];
echo '<br>';
$shown_rows[] = $nr;
}
}
Outputs:
Duplicates:
BX-78|XXX|YUUSATD
BX-78|AAA|FSDSDS
BX-81|XXX|DSDSDSD
I think your 'wanted output' contains an error in the address?
Anyway, with my code above I think you'll have enough mapped data to produce the output you want.
You could do something like this:
$dupes = [];
$current = [];
foreach ($array as $index => $entry) {
$idKey = "id[$index]";
$nameKey = "Name[$index]";
if (array_key_exists($entry[$idKey], $current)) {
$dupes[] = [$entry, $current[$entry[$idKey]]];
}
elseif (array_key_exists($entry[$nameKey], $current)) {
$dupes[] = [$entry, $current[$entry[$nameKey]]];
}
else {
$current[$entry[$idKey]] = $current[$entry[$nameKey]] = $entry;
}
}
print_r($dupes);
Which results in an array containing each set of duplicates (array of arrays):
Array
(
[0] => Array
(
[0] => Array
(
[id[3]] => BX-78
[Name[3]] => AAA
[Address[3]] => FSDSDS
)
[1] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
)
[1] => Array
(
[0] => Array
(
[id[4]] => BX-81
[Name[4]] => XXX
[Address[4]] => DSDSDSD
)
[1] => Array
(
[id[0]] => BX-78
[Name[0]] => XXX
[Address[0]] => YUUSATD
)
)
)
Demo here: https://3v4l.org/JAtNU
In case someone of you are searching unique values by key.
function unique_multidim_array($array, $key) {
$temp_array = array();
$i = 0;
$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;
}
This function just takes multidimensional array and key value of field you need.
Then takes value of given array one by one (smaller arrays).
Then traverses given array and looking if taken key-value pair matches with given key.
After that if taken key-value pair matches with given key function just inserts smaller array in temporary array (array with unique values).
Don't forget to increment indexes of arrays ($i).
Then return array you got (with unique values) after function ends work.

Search nested multidimensional array

I have a function that fills an array:
foreach ($request->get('ids') as $id) {
$pdfArray['other']++; // Yes this is initialized
$pdfArray['rows'][$i]['id'] = $schedule->getId();
$pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
$pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
$pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
$pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
$pdfArray['rows'][$i]['desc'] = $schedule->getDescription();
}
What I want to do
On each loop, I want to check if the array (so far) already has a desc entry equal to the current $schedule->getDescription() AND the same date as $schedule->getStart()->format('d.m.Y') (actually more, but let's keep it simple)
What I tried
public function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && $this->recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
Source
I use it like that:
if ($this->recursive_array_search($schedule->getDescription(), $pdfArray['rows']) &&
$this->recursive_array_search($schedule->getStart()->format('d.m.Y'), $pdfArray['rows'])){
$pdfArray['ma'][$schedule->getId()]++;
}
but this is true when ANY of the start or desc are SOMEWHERE in the current array.
How would I check if desc is found and start is in the SAME $i level?
EDIT for example
Let's say I have 10 $ids to loop through. After 2 loops, the $pdfArray looks like this:
Array
(
[other] => 2
[rows] => Array
(
[0] => Array
(
[id] => 1
[date] => 13.07.2016
[dateSort] => 2016-07-13 08:00
[from] => 08:00
[to] => 09:00
[desc] => TEST
)
[1] => Array
(
[id] => 2
[date] => 12.07.2016
[dateSort] => 2016-07-12 08:00
[from] => 08:00
[to] => 09:00
[desc] => TEST
)
)
)
The next iteration has the following:
$schedule->getStart()->format('d.m.Y') => 12.07.2016
$schedule->getDescription() => TEST
So I want to have the info that the combination already exists in the array.
BUT
$schedule->getStart()->format('d.m.Y') => 12.07.2016
$schedule->getDescription() => TEST2
should NOT return true upon checking of it exists.
To test for a "duplicate" you can use this function:
function testPresence($pdfArray, $desc, $date) {
foreach ($pdfArray["rows"] as $row) {
if ($row["desc"] == $desc && $row["date"] == $date) return true;
}
}
Example use:
echo testPresence($pdfArray, "TEST2", "12.07.2016") ? "Found" : "Not found"; // Not found
echo testPresence($pdfArray, "TEST", "12.07.2016") ? "Found" : "Not found"; // Found
In your original loop, you can use it as follows:
foreach ($request->get('ids') as $id) {
if (testPresence($pdfArray, $schedule->getDescription(),
$schedule->getStart()->format('d.m.Y')) {
// We have a duplicate. Maybe skip this entry?:
continue;
}
$pdfArray['other']++;
$pdfArray['rows'][$i]['id'] = $schedule->getId();
$pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
$pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
$pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
$pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
$pdfArray['rows'][$i]['desc'] = $schedule->getDescription();
}
try this at your validation function
public function array_search($needle1, $needle2 ,$haystack) {
foreach($haystack as $singleArray){
if (in_array($needle1, $singleArray) && in_array($needle2, $singleArray))
return true;
else
continue;
}
return false;
}
and invoke your recursive_array_search like this
if ($this->array_search($schedule->getStart(), $schedule->getDescription(), $pdfArray['rows'])
continue;//Or any other kind of logic you want. At this place you know that description and date staet exist in at your array level
$pdfArray['other']++; // Yes this is initialized
$pdfArray['rows'][$i]['id'] = $schedule->getId();
$pdfArray['rows'][$i]['date'] = $schedule->getStart()->format('d.m.Y');
$pdfArray['rows'][$i]['dateSort'] = $schedule->getStart()->format('Y-m-d H:i');
$pdfArray['rows'][$i]['from'] = $schedule->getStart()->format('H:i');
$pdfArray['rows'][$i]['to'] = $schedule->getEnd()->format('H:i');
$pdfArray['rows'][$i]['desc'] = $schedule->getDescription();
Function version:
/**
* Find matches for $item into pdfArray.
* Returns an index array, possibly empty if no matches.
* #param $item item to find
* #param $rows rows where to search
*/
function findPdfArrayMatches(array $item, array $rows) {
return array_keys(
array_filter(
$rows,
function ($entry) use ($item) {
// These are the matching criteria. More than one row may match.
return $entry['desc'] == $item['desc']
&& $entry['date'] == $item['date']
;
}
)
);
}
You could do like this, in the loop:
$item = [
'id' => $schedule->getId(),
'date' => $schedule->getStart()->format('d.m.Y'),
'dateSort' => $schedule->getStart()->format('Y-m-d H:i'),
'from' => $schedule->getStart()->format('H:i'),
'to' => $schedule->getEnd()->format('H:i'),
'desc' => $schedule->getDescription(),
];
$matches = findPdfArrayMatches($item, $pdfArray['rows']);
if (!empty($matches)) {
...do something with the matches:
foreach ($matches as $match) {
$pdfArray['rows'][$match]['Duplicate'] = true;
}
}
// Add new item
$pdfArray['rows'][$i] = $item;

Compare multidimensional array with simple array

I have two arrays I want to compare these two arrays and find the match. If 807 and 200 appears in same keys like 131 then create third array
array(131=>(807,200));
array1:-
Array([0] => 807,[1] => 200)
array2 :-
$mat= Array([0] => Array([131] => 807),[1] => Array([132] => 807),[2] => Array([125] => 200),[3] => Array([131] => 200))
My code:
<?php
$filtered = array();
array_walk_recursive($matchingskusarr, function($val, $key) use(&$filtered) {
if ($key === 131) {
echo "The key $key has the value $val<br>";
$filtered[$val] = $key;
}
});
echo "<pre>";
print_r($filtered);
echo "</pre>";
?>
You can use array_column like this:
$filtered = array_column($mat, 131);
//Output: Array ( [0] => 807 [1] => 200 )
Update 1:
$matchingskusarr = Array( 0 => Array(131 => 807), 1 => Array(132 => 807),2 => Array(125 => 200),3 => Array(131 => 200)) ;
$skus = array(0=>807, 1=>200);
function yourMatch($skus, $matchingskusarr) {
$continue = [];
foreach ($matchingskusarr as $array) {
//Get the first key !!!
foreach ($array as $key => $value);
//Column already tested just continue
if(isset($continue[$key])) {
continue;
}
//New column we need to check if it matches our $skus
$column = array_column($matchingskusarr, $key);
if($column == $skus) {
return [$key => $column ];
}
$continue[$key] = true;
}
return null;
}
print_r(yourMatch($skus, $matchingskusarr));
Demo: https://3v4l.org/Cr2L4

Search in a multidimensional assoc array

I have an array, looking like this:
[lund] => Array
(
[69] => foo
)
[berlin] => Array
(
[138] => foox2
)
[tokyo] => Array
(
[180] => foox2
[109] => Big entrance
[73] => foo
)
The thing is that there were duplicate keys, so I re-arranged them so I can search more specifically, I thought.
Previously I could just
$key = array_search('foo', $array);
to get the key but now I don't know how.
Question: I need key for value foo, from tokyo. How do I do that?
You can get all keys and value of foo by using this:
foreach ($array as $key => $value) {
$newArr[$key] = array_search('foo', $value);
}
print_r(array_filter($newArr));
Result is:
Array
(
[lund] => 69
[tokyo] => 109
)
If you don't mind about the hard code than you can use this:
array_search('foo', $array['tokyo']);
It just a simple example, you can modify it as per your requirement.
Try this
$a = array(
"land"=> array("69"=>"foo"),
"land1"=> array("138"=>"foo1"),
"land2"=> array('180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'),
);
//print_r($a);
$reply = search_in_array($a, "foo");
print_r($reply);
function search_in_array($a, $search)
{
$result = array();
foreach($a as $key1 => $array ) {
foreach($array as $k => $value) {
if($value == "$search") {
array_push($result,"{$key1}=>{$k}");
breck;
}
}
}
return $result;
}
This function will return the key or null if the search value is not found.
function search($searchKey, $searchValue, $searchArr)
{
foreach ($searchArr as $key => $value) {
if ($key == $searchKey && in_array($searchValue, $value)) {
$results = array_search($searchValue, $value);
}
}
return isset($results) ? $results : null;
}
// var_dump(search('tokyo', 'foo', $array));
Since Question: I need key for value foo, from tokyo. How do i do that?
$key = array_search('foo', $array['tokyo']);
As a function:
function getKey($keyword, $city, $array) {
return array_search($keyword, $array[$city]);
}
// PS. Might be a good idea to wrap this array in an object and make getKey an object method.
If you want to get all cities (for example to loop through them):
$cities = array_keys($array);
I created solution using array iterator. Have a look on below solution:
$array = array(
'lund' => array
(
'69' => 'foo'
),
'berlin' => array
(
'138' => 'foox2'
),
'tokyo' => array
(
'180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'
)
);
$main_key = 'tokyo'; //key of array
$search_value = 'foo'; //value which need to be search
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach ($iterator as $key => $value) {
$keys = array();
if ($value == $search_value) {
$keys[] = $key;
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$keys[] = $iterator->getSubIterator($i)->key();
}
$key_paths = array_reverse($keys);
if(in_array($main_key, $key_paths) !== false) {
echo "'{$key}' have '{$value}' value which traverse path is: " . implode(' -> ', $key_paths) . '<br>';
}
}
}
you can change value of $main_key and $serch_value according to your parameter. hope this will help you.
<?php
$lund = [
'69' => 'foo'
];
$berlin = [
'138' => 'foox2'
];
$tokyo = [
'180' => 'foox2',
'109' => 'Big entrance',
'73' => 'foo'
];
$array = [
$lund,
$berlin,
$tokyo
];
echo $array[2]['180']; // outputs 'foox2' from $tokyo array
?>
If you want to get key by specific key and value then your code should be:
function search_array($array, $key, $value)
{
if(is_array($array[$key])) {
return array_search($value, $array[$key]);
}
}
echo search_array($arr, 'tokyo', 'foo');
try this:
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'On');
$array=array("lund" => array
(
69 => "foo"
),
"berlin" => array
(
138 => "foox2"
),
"tokyo" => array
(
180 => "foox2",
109 => "Big entrance",
73 => "foo"
));
function search($array, $arrkey1, $arrvalue2){
foreach($array as $arrkey=>$arrvalue){
if($arrkey == $arrkey1){
foreach($arrvalue as $arrkey=>$arrvalue){
if(preg_match("/$arrvalue/i",$arrvalue2))
return $arrkey;
}
}
}
}
$result=search($array, "tokyo", "foo"); //$array=array; tokyo="inside array to check"; foo="value" to check
echo $result;
You need to loop through array, since its 2 dimensional in this case. And then find corresponding value.
foreach($arr as $key1 => $key2 ) {
foreach($key2 as $k => $value) {
if($value == "foo") {
echo "{$k} => {$value}";
}
}
}
This example match key with $value, but you can do match with $k also, which in this case is $key2.

PHP find value in multidimensional / nested array

I've trawled the site and the net and have tried various recursive functions etc to no avail, so I'm hoping someone here can point out where I'm going wrong :)
I have an array named $meetingArray with the following values;
Array (
[0] => Array (
[Meet_ID] => 9313
[Meet_Name] => 456136
[Meet_CallInNumber] =>
[Meet_AttendeeCode] =>
[Meet_Password] =>
[Meet_ScheduledDateTime] => 2011-07-18 16:00:00
[Meet_ModeratorCode] =>
[Meet_RequireRegistration] => 0
[Meet_CurrentUsers] => 0
)
[1] => Array (
[Meet_ID] => 9314
[Meet_Name] => 456120
[Meet_CallInNumber] =>
[Meet_AttendeeCode] =>
[Meet_Password] =>
[Meet_ScheduledDateTime] => 2011-07-18 16:00:00
[Meet_ModeratorCode] =>
[Meet_RequireRegistration] => 0
[Meet_CurrentUsers] => 0
)
)
I also have a variable named $meetID.
I want to know if the value in $meetID appears in [Meet_Name] within the array and simply evaluate this true or false.
Any help very much appreciated before I shoot myself :)
function multi_in_array($needle, $haystack, $key) {
foreach ($haystack as $h) {
if (array_key_exists($key, $h) && $h[$key]==$needle) {
return true;
}
}
return false;
}
if (multi_in_array($meetID, $meetingArray, 'Meet_Name')) {
//...
}
I am unsure what you mean by
$meetID appears in [Meet_Name]
but simply substitute the $h[$key]==$needle condition with something that meets your needs.
For single-dimensional arrays you can use array_search(). This can be adapted for multi-dimensional arrays like so:
function array_search_recursive($needle, $haystack, $strict=false, $stack=array()) {
$results = array();
foreach($haystack as $key=>$value) {
if(($strict && $needle === $value) || (!$strict && $needle == $value)) {
$results[] = array_merge($stack, array($key));
}
if(is_array($value) && count($value) != 0) {
$results = array_merge($results, array_search_recursive($needle, $value, $strict, array_merge($stack, array($key))));
}
}
return($results);
}
Write a method something like this:
function valInArr($array, $field, $value) {
foreach ($array as $id => $nestedArray) {
if (strpos($value,$nestedArray[$field])) return $id;
//if ($nestedArray[$field] === $value) return $id; // use this line if you want the values to be identical
}
return false;
}
$meetID = 1234;
$x = valInArr($array, "Meet_Name", $meetID);
if ($x) print_r($array[$x]);
This function will evaluate true if the record is found in the array and also enable you to quickly access the specific nested array matching that ID.

Categories