PHP Creating two dimensional arrays dependent on a function - php

I have an array like this:
[apple] => 11
[pear] => 5
[banana] => 3
[cucumber] => 2
[tomatoes] => 8
I would like to create multi-dimensional array like this:
[randomArrayName1]
[apple] => 11
[banana] => 3
[tomatoes] => 8
[randomArrayName2]
[pears] => 5
[cucumber] => 2
I wrote this below but it is not working and I have no clue how to make it do: what I need it to do
$quantity = array();
foreach($fruit as $key => $value) {
$quantity = Finder($key);
}
randomArrayName1 and randomArrayName2 will be generated depending on Finder() function's result. Depending on that result I want fruit array to be created as a second dimension array.
Solution:
The problem was that the function I wrote that created names like randomArrayName1, randomArrayName2... was in fact a XML function. Therefore, result of this function was not an array, it was XML simple object. This caused problem on creating multidimensional array. Once I implemented the code below it converted SimpleXML to Array and code worked fine.
$type is SimpleXML array
$out is result array
foreach ( (array) $type as $index => $node )
$out[$index] = ( is_object ( $node ) ) ? xml2array ( $node ) : $node;

You can use array_reduce. It takes three arguments, an initial array to operate on, a function which should operate on each element (which in turn requires two arguments, $carry, which is a variable that gets passed through to the function each time through the return statement, and $item, which is the array item being operated on) and finally an "initial" value for $carry within the function, which in this case is going to be our multidimensional array that gets eventually returned.
This is an example where the Finder function returns a key based on whether the value of the items in the array is odd or even, and sorts the values accordingly.
Note that we are operating on the array_keys of fruits, so that we have access to both key and value inside our reducer.
<?php
$fruit = ['apple' => 11, 'pear' => 5, 'banana' => 3, 'cucumber' => 2, 'tomatoes' => 8];
function Finder($fruit) {
return $fruit % 2 == 0 ? 'even' : 'odd';
}
$multi = array_reduce(array_keys($fruit), function($carry, $item) use ($fruit) {
$val = $fruit[$item];
$carry[Finder($val)][$item] = $val;
return $carry;
}, []);
var_dump($multi);
/* // output
array(2) {
["odd"]=>
array(3) {
["apple"]=>
int(11)
["pear"]=>
int(5)
["banana"]=>
int(3)
}
["even"]=>
array(2) {
["cucumber"]=>
int(2)
["tomatoes"]=>
int(8)
}
}
*/

You need to create the new index or access it if it has already been created and then create another element under that with the existing key and assign the value:
$quantity = array();
foreach($fruit as $key => $value) {
$quantity[Finder($key)][$key] = $value;
}
This is assuming that Finder() is returning a string like randomArrayName1.

Related

FOR-EACH control structures with an array display only the last value [duplicate]

I have an associative array, however when I add values to it using the below function it seems to overwrite the same keys. Is there a way to have multiple of the same keys with different values? Or is there another form of array that has the same format?
I want to have:
42=>56
42=>86
42=>97
51=>64
51=>52
etc etc
Code:
function array_push_associative(&$arr) {
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
foreach ($arg as $key => $value) {
$arr[$key] = $value;
$ret++;
}
}else{
$arr[$arg] = "";
}
}
return $ret;
}
No, you cannot have multiple of the same key in an associative array.
You could, however, have unique keys each of whose corresponding values are arrays, and those arrays have multiple elements for each key.
So instead of this...
42=>56 42=>86 42=>97 51=>64 51=>52
...you have this:
Array (
42 => Array ( 56, 86, 97 )
51 => Array ( 64, 52 )
)
A key is an extension of a variable. If you overwrite the variable... You overwrite the variable.
No, you cannot have. A workaround I use is to have each key/value pair as a new array with 2 elements:
$test = array(
array(42,56),
array(42,86),
array(42,97),
array(51,64),
array(51,52)
)
For example, you can access the second key (=42) using:
$test[1][0]
and the second value(=86) using:
$test[1][1]
I found this question while researching the exact opposite intended outcome, I have an array of data that has duplicate keys! Here's how I did it (still trying to figure out where in my process things are messing up).
$session = time();
$a = array();
$a[(string)$session] = 0;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
)
*/
var_dump($a);
/* output:
array(1)
(
[1510768034] => int(0)
)
*/
print_r($j);
/* output:
{"1510768034":0}
*/
$a = (array)json_decode($j);
$session = #array_pop(array_keys($a));
$a[(string)$session] = 10;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
[1510768034] => 10
)
*/
var_dump($a);
/* output:
array(2)
(
'1510768034' => int(0)
[1510768034] => int(10)
)
*/
print_r($j);
/* output:
{"1510768034":0,"1510768034":10}
*/
Yup....that just happened.
PHP 7.1
Edit: It's similar in PHP 7.2.10, except json_encode no longer entertains duplicate keys, encoded strings are correct. The array, however, can have matching string and integer keys.
i had the same need too create an array with the same keys, (just to keep performance by using two loops rather than 4 loops).
by using this : [$increment."-".$domain_id] => $article_id;
my list of articles in each domain looks like this after a print_r() :
$AllSa = Array
(
[1-5] => 143
[2-5] => 176
[3-5] => 992
[4-2] => 60
[5-2] => 41
[6-2] => 1002
[4-45] => 5
[5-45] => 18
[6-45] => 20
)
And then by looping through this table to associate article by domain :
$AssocSAPerDomain = array();
$TempDomain = "";
$TempDomain_first = 0;
foreach($tree_array as $id_domain => $id_sa){
if( !$TempDomain && $TempDomain_first == 0 ){ $TempDomain = substr(strrchr($id_domain, "-"), 1); $TempDomain_first = 1; }
$currentDomain = substr(strrchr($id_domain, "-"), 1);
//if($TempDomain == $currentDomain)
$AssocSAPerDomain[$currentDomain][] = $id_sa;
$TempDomain = substr(strrchr($id_domain, "-"), 1);
}
you get this
$assoc= Array
(
[5] => 143
=> 176
=> 992
[2] => 60
=> 41
=> 1002
[45]=> 5
=> 18
=> 20
)
it is not possible technically. But I created a fun way to do it. Be alert, this answer is just for the fun, the ultimate goal is to get the output anyway.
So here is the answer. You first need to convert to the whole array to the string. Then the rest of the things is just string replace and a little code.
<?php
$ary="array('a'=>123,'a'=>161,'a'=>195)";
$str = str_replace("array(", "", $ary);
$str = str_replace(")", "", $str);
$arr = explode(",",$str);
foreach($arr as $element){
$element = str_replace("=>", "", $element);
$element = str_replace("'", "", $element);
echo $element.'<br>';
}
?>
Here is the output

Remove the whole array elements, where array element key count < 2 in PHP

Below is my code that output this array:
// update users
$where_in = array('1102','');
$admin_data = $this->db->select('id,email,domain')->where_in('id',$where_in)->get('users')->result();
echo "<pre>";print_r($admin_data);
current output array
1102,
Array
(
[0] => stdClass Object
(
[id] => 1
)
)
1111,
Array
(
[0] => stdClass Object
(
[id] => 1132
)
[1] => stdClass Object
(
[id] => 1133
)
)
I am trying to accomplish by doing this, but not getting expected result.
foreach ($admin_data as $key) {
if (count($admin_data) < 2) {
unset($admin_data);
}
}
Expected result: I want to remove whole array element, where array key less than 2. I wish to get only array with more than 1 key count like below:
1111,
Array
(
[0] => stdClass Object
(
[id] => 1132
)
[1] => stdClass Object
(
[id] => 1133
)
)
I believe you are trying to unset elements within your "$admin_data" array, however you call unset on the array itself. If you pass the index of the array element into your loop, with the element itself, then you can check if the element has less than two inner elements, and unset that element accordingly.
$elementsToRemove = [];
foreach($admin_data as $index => $key) {
if (count($key) < 2) {
$elementsToRemove[] = $index;
}
}
$newArray = array_diff_key($admin_data, array_flip($elementsToRemove));
I'm not sure if I understood, but if you have an array of arrays and want to remove the inner arrays with less than 2 elements, you could do:
<?php
$original = [
["a"],
["b", "c"],
];
$filtered = array_filter(
$original,
function ($innerArray) {
return count($innerArray) >= 2;
}
);
print_r($filtered);
The result is
Array
(
[1] => Array
(
[0] => b
[1] => c
)
)
PHP Fiddle
Check again your code, it contains some logical problems:
foreach ($admin_data as $key) {
if (count($admin_data) < 2) {
unset($admin_data);
}
}
If $admin_data has one item, the if (count($admin_data) < 2) test is true and
unset($admin_data); is executed. That means (simplifying) that the all the contents of $admin_data are deleted.
If $admin_data has two or more items, the if (count($admin_data) < 2) test is never true. And it is so for each iteration.
Both cases are not logical, because you do not need the foreach loop for this test to work. Besides, you might not want to delete $admin_data contents.
What you need to do, is to iterate through $admin_data items, check the item to see if it is an array and if that array has one item, remove the item from the $admin_data array. Or you could create another array only with the valid items.
Here is a possible example of both:
/* unset the item if it is an array with one item */
foreach ($admin_data as $key => $value) {
if (is_array($value) && count($value) === 1) {
unset($admin_data[$key]);
}
}
/* create a new array with the valid items */
$valid_admin_data = [];
foreach ($admin_data as $key => $value) {
if (is_array($value) && count($value) > 1) {
$valid_admin_data[$key] = $value;
}
}
I would also suggest you to read again the foreach documentation. Also, be consistents with names of variables, since it helps avoid misunderstandings: for instance, foreach ($admin_data as $key) could be better named to foreach ($admin_data as $value), since with one variable, you extract the value of current item.

Access newly added key=>value in associative array during loop

I am trying to add a key=>value pair to an array while using a foreach loop, when that value is added the foreach loop needs to process the new key=>value pair.
$array = array(
'one' => 1,
'two' => 2,
'three' => 3
);
foreach($array as $key => $value) {
if ($key == 'three') {
$array['four'] = 4;
} else if ($key == 'four') {
$array['five'] = 5;
}
}
If I print the array after the loop, I would expect to see all 5 kv's, but instead I only see this:
Array
(
[one] => 1
[two] => 2
[three] => 3
[four] => 4
)
Is there some way, when I add the fourth pair, to actually process it so the fifth pair gets added within that foreach loop (or another kind of loop?)
According to php documentation,
As foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior.
You cannot modify the array during foreach. However, an user posted an example of a regular while loop that does what you need: http://www.php.net/manual/en/control-structures.foreach.php#99909
I report it here
<?php
$values = array(1 => 'a', 2 => 'b', 3 => 'c');
while (list($key, $value) = each($values)) {
echo "$key => $value \r\n";
if ($key == 3) {
$values[4] = 'd';
}
if ($key == 4) {
$values[5] = 'e';
}
}
?>
the code above will output:
1 => a
2 => b
3 => c
4 => d
5 => e
That's because PHP will internally use it's own copy of the array pointer. You are iterating trough it's orginal key/values not through the modified array.
As the original array contains the key three, the first if statement will match, but not the second
Another simpler example is the fact, that this is not an infinite loop:
$array = array(1);
foreach($array as $val) {
$array []= $val +1;
}
var_dump($array);
Output:
array(2) {
[0] =>
int(1)
[1] =>
int(2)
}
However, the PHP documentation says not much to that:
As foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior.

How to count elements inside array/object on PHP?

I have this array being sent to my view
Array
(
[0] => stdClass Object
(
[emg_id] => 2
[fkit] => 1
[door] =>
)
)
I would like to count how many elements are empty, NULL, or '0'.
I tried using count but it always returns '1', instead of counting all of the elements, so I can later determine which satisfy my conditions above.
Any ideas what I'm doing wrong?
// number of "null" elements
echo count(array_filter((array) $array[0], 'is_null'));
There are some other is_*()-functions built-in, that may help you for example to count the number of strings (and so on).
To test, if an element is (e.g.) 0, I suggest to use an anonymous function
echo count(array_filter((array) $array[0], function ($item) {
return $item === 0;
}));
The other cases are similar.
loop through them and count.
function loopMe($array, $value) {
$num = 0;
foreach($array as $key=>$val) {
if($val == $value)
$num++;
}
return $num;
}
$ar = array (
array (
"emg_id" => 2
"fkit" => 1
"door" => null));
$num = loopMe($ar[0], null);

PHP Associative Array Duplicate Keys

I have an associative array, however when I add values to it using the below function it seems to overwrite the same keys. Is there a way to have multiple of the same keys with different values? Or is there another form of array that has the same format?
I want to have:
42=>56
42=>86
42=>97
51=>64
51=>52
etc etc
Code:
function array_push_associative(&$arr) {
$args = func_get_args();
foreach ($args as $arg) {
if (is_array($arg)) {
foreach ($arg as $key => $value) {
$arr[$key] = $value;
$ret++;
}
}else{
$arr[$arg] = "";
}
}
return $ret;
}
No, you cannot have multiple of the same key in an associative array.
You could, however, have unique keys each of whose corresponding values are arrays, and those arrays have multiple elements for each key.
So instead of this...
42=>56 42=>86 42=>97 51=>64 51=>52
...you have this:
Array (
42 => Array ( 56, 86, 97 )
51 => Array ( 64, 52 )
)
A key is an extension of a variable. If you overwrite the variable... You overwrite the variable.
No, you cannot have. A workaround I use is to have each key/value pair as a new array with 2 elements:
$test = array(
array(42,56),
array(42,86),
array(42,97),
array(51,64),
array(51,52)
)
For example, you can access the second key (=42) using:
$test[1][0]
and the second value(=86) using:
$test[1][1]
I found this question while researching the exact opposite intended outcome, I have an array of data that has duplicate keys! Here's how I did it (still trying to figure out where in my process things are messing up).
$session = time();
$a = array();
$a[(string)$session] = 0;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
)
*/
var_dump($a);
/* output:
array(1)
(
[1510768034] => int(0)
)
*/
print_r($j);
/* output:
{"1510768034":0}
*/
$a = (array)json_decode($j);
$session = #array_pop(array_keys($a));
$a[(string)$session] = 10;
$j = json_encode($a,JSON_FORCE_OBJECT);
print_r($a);
/* output:
Array
(
[1510768034] => 0
[1510768034] => 10
)
*/
var_dump($a);
/* output:
array(2)
(
'1510768034' => int(0)
[1510768034] => int(10)
)
*/
print_r($j);
/* output:
{"1510768034":0,"1510768034":10}
*/
Yup....that just happened.
PHP 7.1
Edit: It's similar in PHP 7.2.10, except json_encode no longer entertains duplicate keys, encoded strings are correct. The array, however, can have matching string and integer keys.
i had the same need too create an array with the same keys, (just to keep performance by using two loops rather than 4 loops).
by using this : [$increment."-".$domain_id] => $article_id;
my list of articles in each domain looks like this after a print_r() :
$AllSa = Array
(
[1-5] => 143
[2-5] => 176
[3-5] => 992
[4-2] => 60
[5-2] => 41
[6-2] => 1002
[4-45] => 5
[5-45] => 18
[6-45] => 20
)
And then by looping through this table to associate article by domain :
$AssocSAPerDomain = array();
$TempDomain = "";
$TempDomain_first = 0;
foreach($tree_array as $id_domain => $id_sa){
if( !$TempDomain && $TempDomain_first == 0 ){ $TempDomain = substr(strrchr($id_domain, "-"), 1); $TempDomain_first = 1; }
$currentDomain = substr(strrchr($id_domain, "-"), 1);
//if($TempDomain == $currentDomain)
$AssocSAPerDomain[$currentDomain][] = $id_sa;
$TempDomain = substr(strrchr($id_domain, "-"), 1);
}
you get this
$assoc= Array
(
[5] => 143
=> 176
=> 992
[2] => 60
=> 41
=> 1002
[45]=> 5
=> 18
=> 20
)
it is not possible technically. But I created a fun way to do it. Be alert, this answer is just for the fun, the ultimate goal is to get the output anyway.
So here is the answer. You first need to convert to the whole array to the string. Then the rest of the things is just string replace and a little code.
<?php
$ary="array('a'=>123,'a'=>161,'a'=>195)";
$str = str_replace("array(", "", $ary);
$str = str_replace(")", "", $str);
$arr = explode(",",$str);
foreach($arr as $element){
$element = str_replace("=>", "", $element);
$element = str_replace("'", "", $element);
echo $element.'<br>';
}
?>
Here is the output

Categories