I want to create an array using recursion in Codeigniter. my function make_tree() in controller is :
function make_tree($customer_id,$arr = array()){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
echo $customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id);
endforeach;
var_dump($arr);
}
But the var_dump($arr) and echo results output like:
1013
array
empty
array
0 => string '13' (length=2)
11
array
empty
array
0 => string '10' (length=2)
1 => string '11' (length=2)
How can I make a single array of all the three outputs, ie an array with elements 13,10,11
you need to send the array with the parameters otherwise a new array is created.
function make_tree($customer_id,$arr = array()){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
echo $customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id, $arr);
endforeach;
var_dump($arr);
}
PS: I don't know what you are trying to do exactly, but you probably need to add a stopping condition that is going to return the final array, unless you want to pass it by reference.
UPDATE
Here is one way to do it:
function make_tree($customer_id, &$arr)
{
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
$customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id, $arr);
endforeach;
}
and this is how you'd use it:
$final_array = array();
make_tree($some_customer_id, $final_array);
// now the $final_array is populated with the tree data
You can use class scope.
class TheController {
private $arr = array();
function make_tree($customer_id){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v) {
$customer_id = $v['customer_id'];
array_push($this->arr, $customer_id);
$this->make_tree($customer_id);
}
}
}
Related
I have an array that looks like this.
$array = [
0 => 'abc',
1 => [
0 => 'def',
1 => 'ghi'
],
'assoc1' => [
'nassoc' => 'jkl',
'nassoc2' => 'mno',
'nassoc3' => '',
'nassoc4' => false
]
];
The $array can have numeric keys or be an assoc array or a mixed one. The level of nesting is not known. Also the values of the array can also be bool or null or an empty string ''
I need to able to convert this into a scalar array with key value pairs. And then later reconvert it back to the exact same array.
So the scalar array could look like
$arrayScalar = [
'0' => 'abc',
'1[0]' => 'def',
'1[1]' => 'ghi',
'assoc1[nassoc]' => 'jkl',
'assoc1[nassoc2]' => 'mno',
'assoc1[nassoc3]' => '',
'assoc1[nassoc4]' => false
];
And then later be able to get back to the initial $array.
I wrote a parser and it does not currently handle bool values correctly.
I have a feeling this is at best a super hacky method to do what I am after. Also I have been able to test it only so much.
function flattenNestedArraysRecursively($nestedArray, $parent = '', &$flattened = [])
{
$keys = array_keys($nestedArray);
if (empty($keys)) {
$flattened[$parent] = 'emptyarray';
} else {
foreach ($keys as $value) {
if (is_array($nestedArray[$value])) {
$reqParent = (!empty($parent)) ? $parent . '|!|' . $value : $value;
$this->flattenNestedArraysRecursively($nestedArray[$value], $reqParent, $flattened);
} else {
$reqKey = (!empty($parent)) ? $parent . '|!|' . $value : $value;
$flattened[$reqKey] = $nestedArray[$value];
}
}
}
return $flattened;
}
function reCreateFlattenedArray($flatArray): array
{
$arr = [];
foreach ($flatArray as $key => $value) {
$keys = explode('|!|', $key);
$arr = $this->reCreateArrayRecursiveWorker($keys, $value, $arr);
}
return $arr;
}
function reCreateArrayRecursiveWorker($keys, $value, $existingArr)
{
//Outside to Inside
$keyCur = array_shift($keys);
//Check if keyCur Exists in the existingArray
if (key_exists($keyCur, $existingArr)) {
// Check if we have reached the deepest level
if (empty($keys)) {
//Return the Key => value mapping
$existingArr[$keyCur] = $value;
return $existingArr;
} else {
// If not then continue to go deeper while appending deeper levels values to current key
$existingArr[$keyCur] = $this->reCreateArrayRecursiveWorker($keys, $value, $existingArr[$keyCur]);
return $existingArr;
}
} else {
// If Key does not exists in current Array
// Check deepest
if (empty($keys)) {
//Return the Key => value mapping
$existingArr[$keyCur] = $value;
return $existingArr;
} else {
// Add the key
$existingArr[$keyCur] = $this->reCreateArrayRecursiveWorker($keys, $value, []);
return $existingArr;
}
}
}
Is there a better more elegant way of doing this, maybe http_build_query or something else I am not aware of.
Sandbox link -> http://sandbox.onlinephpfunctions.com/code/50b3890e5bdc515bc145eda0a1b34c29eefadcca
Flattening:
Your approach towards recursion is correct. I think we can make it more simpler.
We loop over the array. if the value is an array in itself, we recursively make a call to this new child subarray.
This way, we visit each key and each value. Now, we are only left to manage the keys to assign them when adding to our final resultant array, say $arrayScalar.
For this, we make a new function parameter which takes the parent key into account when assigning. That's it.
Snippet:
$arrayScalar = [];
function flatten($array,&$arrayScalar,$parent_key){
foreach($array as $key => $value){
$curr_key = empty($parent_key) ? $key : $parent_key . '[' . $key . ']';
if(is_array($value)){
flatten($value,$arrayScalar,$curr_key);
}else{
$arrayScalar[$curr_key] = $value;
}
}
}
flatten($array,$arrayScalar,'');
var_export($arrayScalar);
Demo: http://sandbox.onlinephpfunctions.com/code/1e3092e9e163330f43d495cc9d4acb672289a987
Unflattening:
This one is a little tricky.
You might have already noticed that the keys in the flattened array are of the form key1[key2][key3][key4] etc.
So, we collect all these individually in a new array, say $split_key. It might look like this.
array (
'key1',
'key2',
'key3',
'key4',
)
To achieve the above, we do a basic string parsing and added in-between keys to the array whenever we reach the end of the key string or [ or ].
Next, to add them to our final resultant array, we loop over the collected keys and check if they are set in our final array. If not so, set them. We now pass child array reference to our temporary variable $temp. This is to edit the same copy of the array. In the end, we return the result.
Snippet:
<?php
function unflatten($arrayScalar){
$result = [];
foreach($arrayScalar as $key => $value){
if(is_int($key)) $key = strval($key);
$split_key = [];
$key_len = strlen($key);
$curr = '';
// collect them as individual keys
for($i = 0; $i < $key_len; ++$i){
if($key[ $i ] == '[' || $key[ $i ] == ']'){
if(strlen($curr) === 0) continue;
$split_key[] = $curr;
$curr = '';
}else{
$curr .= $key[ $i ];
}
if($i === $key_len - 1 && strlen($curr) > 0){
$split_key[] = $curr;
}
}
// collecting them ends
//add them to our resultant array.
$temp = &$result;
foreach($split_key as $sk){
if(!isset($temp[ $sk ])){
$temp[ $sk ] = [];
}
$temp = &$temp[$sk];
}
$temp = $value;
}
return $result;
}
var_export(unflatten($arrayScalar));
Demo: http://sandbox.onlinephpfunctions.com/code/66136a699c3c5285eed3d3350ed4faa5bbce4b76
I am querying a service if a person have phone number(s) (also maybe not). I have a json string (as return value) like the following:
$json = '{"data":[{"tel1":"1102"},{"tel2":"3220"}],"found":true}';
I convert this string to json_decode() function.
$jd = json_decode($json);
Then I want to get the phone numbers only into an array without keys.
if($jd->found) {
$o2a = get_object_vars($json);
}
var_dump($o2a);
When I want to see what $o2a holds with var_dump() function, I get the following:
array (size=2)
'data' =>
array (size=2)
0 =>
object(stdClass)[2]
public 'tel1' => string '1219' (length=4)
1 =>
object(stdClass)[3]
public 'tel2' => string '2710' (length=4)
'found' => boolean true
I want to get only the phone numbers into an array at the end like:
$phones = array('1219', '2710');
What makes me stop doing this is that I do not know how many phone numbers one can have. Json array could consist of more or less elements.
$possibleJson1 = '{"data":[],"found":false}'; //no phone number found
$possibleJson2 = '{"data":[{"tel1":"1102"},{"tel2":"3220"},{"tel3":"1112"},{"tel4":"3230"}],"found":true}'; //4 phone numbers found
It may vary 0-to-n, so if it was a constant number I could create that array within a loop.
Some functions without any code :)
$json = '{"data":[{"tel1":"1102"},{"tel2":"3220"}],"found":true}';
$vals = array_values(array_reduce(json_decode($json, true)['data'], 'array_merge',[]));
var_dump($vals);
Convert it into an array and then you should be able to iterate it easily
$jd = json_decode($json, true);
$phones = array();
if(isset($jd['data']) && $jd['found']) {
foreach($jd['data'] as $key => $val) $phones[] = $val;
}
Instead of handling with an object, use the second parameter of the json_decode function so it would returned an array.
Check if the data and found keys exist.
Since you don't know what are the keys names, you can use array_values
Demo
.
$jd = json_decode($json, true);
if(isset($jd['data']) && isset($jd['found'])){
$telArr = $jd['data'];
$phones = array();
foreach($telArr as $tel){
$value = array_values($tel);
$phones[] = $value[0];
}
var_dump($phones);
}
Output:
array(2) {
[0]=>
string(4) "1102"
[1]=>
string(4) "3220"
}
Well, I would try something like that:
$json = '{"data":[{"tel1":"1102"},{"tel2":"3220"}],"found":true}';
$jd = json_decode($json);
$phones = [];
if ($jd->found && count($jd->data)) {
foreach ($jd->data as $key -> $value) {
$phones[] = $value;
}
}
Try as using in_array and simple foreach loop
$json = '{"data":[{"tel1":"1102"},{"tel2":"3220"}],"found":true}';
$arr = json_decode($json, true);
$result = array();
if (in_array(true, $arr)) {
foreach ($arr['data'] as $key => $value) {
foreach($value as $k => $v)
$result[] = $v;
}
}
print_r($result);
Fiddle
I am trying to make first array value to uppercase.
Code:
$data = $this->positions_model->array_from_post(array('position', 'label'));
$this->positions_model->save($data, $id);
So before save($data, $id) to database I want to convert position value to uppercase. I have tried by this
$data['position'] = strtoupper($data['position']);
but than it is not storing the value in db with uppercase but as it is what user inputs.
Current output of $data:
Array ( [position] => it [label] => Information Technology )
And I want it in uppercase as IT
Added Model Method
public function get_positions_array($id = NULL, $single = FALSE)
{
$this->db->get($this->_table_name);
$positions = parent::get($id, $single);
$array = array();
foreach($positions as $pos){
$array[] = get_object_vars($pos);
}
return $array;
}
Main MY_Model method
public function array_from_post($fields)
{
$data = array();
foreach ($fields as $field) {
$data[$field] = $this->input->post($field);
}
return $data;
}
This should work:
$data = $this->positions_model->array_from_post(array('position', 'label'));
$data['position'] = strtoupper($data['position']);
$this->positions_model->save($data, $id);
If Its not, then $data array have only read attribute.
The array_from_post() method returns an array with the format below:
$data = array(
'position' => 'it',
'label' => 'Information Technology'
);
So, you could make first value of the array to uppercase, by using array_map or array_walk functions as follows:
$data = array_map(function($a) {
static $i = 0;
if ($i === 0) { $i++; return strtoupper($a); }
else return $a;
}, $array);
Note: This only works on PHP 5.3+, for previous versions, use the function name instead.
Here is the array_walk example, which modifies the $data:
array_walk($data, function(&$value, $key) {
static $i = 0;
if ($i == 0) { $i++; $value = strtoupper($value); }
});
Again, if you're using PHP 5.2.x or lower, you could pass the function name instead.
I have an array which contains a great deal of data, which has been generated from a JSON file. Most of the data is used to populateinput elements, but some of the keys contain hidden, default values to be used for calculations later.
The array looks something like this:
[name] => 'My App'
[default_E17] => 0.009
[default_H17] => 0.0236
[default_K17] => 50
[default_P17] => 0.0118
[default_E19] => 0.03
I want to loop over all default_* keys, and output them using HTML. Essentially, I want a foreach loop, but only for the keys whose format matches default_*. Does anyone know if this is possible?
Please note that the values in the array before [default_*] keys is variable length, so I cannot easily use an array_splice().
You use strpos($key, "default_") === 0 to show that it start with default_ and its not in the middle or end
$array = array();
$array['name'] = 'My App';
$array['default_E17'] = "0.009";
$array['default_H17'] = "0.0236";
$array['default_K17'] = "50";
$array['default_P17'] = "0.0118";
$array['default_E19'] = "0.03";
$array['E19_default_test'] = "1.03";
echo "<pre>";
* You can use foreach *
$list = array();
foreach ( $array as $key => $value ) {
if (strpos($key, "default_") === 0) {
$list[$key] = $value;
}
}
var_dump($list);
You can also use array_flip with array_filter
$array = array_flip(array_filter(array_flip($array),function($var) { return (strpos($var, "default_") === 0);}));
var_dump($array);
You can also use FilterIterator
class RemoveDefaultIterator extends FilterIterator {
public function accept() {
return (strpos($this->key(), "default_") === 0);
}
}
$list = new RemoveDefaultIterator(new ArrayIterator($array));
var_dump(iterator_to_array($list));
They would all Output
array
'default_E17' => string '0.009' (length=5)
'default_H17' => string '0.0236' (length=6)
'default_K17' => string '50' (length=2)
'default_P17' => string '0.0118' (length=6)
'default_E19' => string '0.03' (length=4)
foreach( $arr as $k => $v ) { //iterate the array
if( strpos($k, 'default_') !== FALSE ) //search if the key contains 'default_'
$default_values[] = $v; // if so, store the values for the 'default_' keys
}
Just iterate over your array
Foreach( $inputArray AS $key=>$val ) {
// check if key is the one we need
if( ... ) {
// it is - deal with it
}
}
depending of the keys you use if() can be simple substr() or regexp matching.
You can use a FilterIterator for this.
Its essetially the same as looping over the whole array, because that's the only way really, but it strips you from doing this in your productive loop, thus generating less noise.
Here's how:
class Default_FilterIterator extends FilterIterator
{
public function accept()
{
if (strpos($this->key(), 'default') === 0) {
return true;
}
return false;
}
}
$yourArray = array('default_stuff' => 'foo', 'otherstuff' => 'bar');
$filterdArray = new Default_FilterIterator(new ArrayIterator($yourArray));
foreach ($filteredArray as $key => $value) {
//deal only with default values here
}
foreach ($your_array as $key => $value) {
// check if the $key starst with 'default_'
if (substr($key, 0, 8) == "default_") {
//do your thing...
echo "<input type='text' value='" . $value . "'>";
}
}
I'm using some php functions for security.
function whileToArray($qr)
{
while($rs = mysql_fetch_assoc($qr))
{
$data[] = $rs;
}
$data = array_map('htmlspecialchars_decode',$data);
$data = array_map('htmlentities',$data);
return $data;
}
When i running this code, I get;
Warning: htmlspecialchars_decode() expects parameter 1 to be string, array given in C:\AppServ\www\bigbeng\classes\get.class.php on line 22
Warning: htmlspecialchars_decode() expects parameter 1 to be string, array given in C:\AppServ\www\bigbeng\classes\get.class.php on line 22
print_r($data):
Array ( [0] => Array ( [kategori_id] => 1 [kategori_adi] => Spor )
[1] => Array ( [kategori_id] => 2 [kategori_adi] => Siyaset ) )
How can i use these functions with array?
array_map works with 1D array not on multidimensional array. so try with below function
function array_map_recursive($fn, $arr) {
$rarr = array();
foreach ($arr as $k => $v) {
$rarr[$k] = is_array($v)
? array_map_recursive($fn, $v)
: $fn($v); // or call_user_func($fn, $v)
}
return $rarr;
}
then call
$data = array_map_recursive('htmlspecialchars_decode',$data);
You should move your decoding logic inside the inner while loop:
function whileToArray($qr)
{
while($rs = mysql_fetch_assoc($qr))
{
$rs = array_map('htmlspecialchars_decode',$rs);
$rs = array_map('htmlentities',$rs);
$data[] = $rs;
}
return $data;
}
This is a very incorrect approach though. Your logic assumes that absolutely all data stored in your database is HTML-encoded; IDs, numeric values, timestamps, everything. You should not HTML-encode any data in your database, HTML-encoding should be performed only when you actually want to embed a value in HTML.