Multidimensional Array (with some values not sub-arrays) to string? - php

I am trying to turn a multidimensional array into a patterned string with this array_map function:
function array_to_string($array) {
return implode("&",array_map(function($a){return implode("~",$a);},$array));
}
$arr = array("hello",array("blue","red"),array("one","three","twenty"),"random");
array_to_string($arr);
Between each array element "&" and between each sub-array element (if it is an array) "~"
Should Output: hello&blue~red&one~three~twenty&random
However this outputs: Warning: implode(): Invalid arguments passed (2)
I tried changing the function within the array_map to detect whether the multi-array's value is_array but from my outputs, I don't think that is possible? So essentially, I guess the real question is how can I place a test on the array_map function to see whether or not it is_array

Since $a can be an array or a string, you should check it in your callback function:
function array_to_string($array) {
return implode("&",
array_map(function($a) {
return is_array($a) ? implode("~",$a) : $a;
}, $array)
);
}

Related

Remove array element by checking a value php

I have an array as follows
[0=>['classId'=>2,'Name'=>'John'],1=>['classId'=>3,'Name'=>'Doe'],2=>['classId'=>4,'Name'=>'Stayne']]
I need to remove the elements with classId 2 or 4 from array and the expected result should be
[0=>['classId'=>3,'Name'=>'Doe']]
How will i achieve this without using a loop.Hope someone can help
You can use array_filter in conjunction with in_array.
$array = [0=>['classId'=>2,'Name'=>'John'],1=>['classId'=>3,'Name'=>'Doe'],2=>['classId'=>4,'Name'=>'Stayne']];
var_dump(
array_filter($array, function($item){return !in_array($item["classId"], [2,4]);})
);
Explanation
array_filter
Removes elements from the array if the call-back function returns false.
in_array
Searches an array for a value; returns boolean true/false if the value is (not)found.
Try this:
foreach array as $k => $v{
if ($v['classId'] == 2){
unset(array[$k]);
}
}
I just saw your edit, you could use array_filter like so:
function class_filter($arr){
return ($arr['classId'] == "whatever");
}
array_filter($arr, "class_filter");
Note: you'll still need to loop through a multi-dimensional array I believe.

Why PHP have so weird function parameter positioning?

PHP is easy language to learn but one thing that's triggering me is PHP's positions of function parameters.
Example #1
array_walk($array, $callback);
array_map($callback, $array);
Example #2
array_push($array, $mixed);
array_search($mixed, $array);
It just don't make any sense. Does PHP developers make this intentionally?
It's all to do with what they do with an array. array_walk modifies the array by reference whilst array_map returns a new array.
Again, array_push modifies the array by reference and array_search returns a value from the array.
Where the array comes first in the arguments; will tend to mean the array will be modified by the function. It's very useful as a developer to know which functions are likely to modify the array being passed in.
Example:
<?php
$myArray = [1,2,3];
array_push($myArray,4);
var_dump($myArray); // array(1,2,3,4);
$myArray = [1,2,3];
$result = array_map(function ($val) { return $val * 2; }, $myArray);
var_dump($myArray); // array(1,2,3);
var_dump($result); // array(2,4,6);

array_map and htmlentities

I've been trying using array_map to convert characters to HTML entities with htmlentities() like this:
$lang = array_map('htmlentities', $lang);
My array looks like this:
$lang = array();
$lang['var_char1']['varchar2'] = 'Some Text';
But I keep getting this errors:
Warning: htmlentities() expects parameter 1 to be string, array given
in /home/user/public_html/foo/lang/en.inc.php on line 1335
Does anyone know what could be the problem? Thank you!
Use array_walk_recursive. array_map doesn't work with multidimensional arrays:
array_walk_recursive($lang, function (&$value) {
$value = htmlentities($value);
});
Because $lang is a two dimensional array, so it won't work
For two dimensional array you need to use for loop
foreach($$lang as &$l):
$l = array_map('htmlentities', $l);
}
$lang['var_char1']['varchar2'] defines a multidimensional array, so each element of $lang is also an array. array_map() iterates through $lang, passing an array to htmlentities() instead of a string.
array_map() doesn't work recursively. If you know your array is always two levels deep you could loop through it and use array_map on the sub-arrays.
if you like quotes
function stripslashes_array(&$arr) {
array_walk_recursive($arr, function (&$val) {
$val = htmlentities($val, ENT_QUOTES);
});
}
multiple array in post, get, dll
stripslashes_array($_POST);
stripslashes_array($_GET);
stripslashes_array($_REQUEST);
stripslashes_array($_COOKIE);
Each element in $lang is an array, so the function you pass to array_map should take an array as an argument. That is not the case for 'htmlentities' which takes a string.
You can:
$map_htmlentities = function(array) { return array_map('htmlentities', array); };
and then
$lang = array_map($map_htmlentities, $lang);
From PHP 7.4 on you can use lambdas:
$lang = array_map(fn($arr) => array_map('htmlentities', $arr), $lang);

convert string to php arguments

so suppose I have a function:
function j($a, $b){
return $a + $b;
}
and then I put the intended arguments of the function into a string:
$str = '1,3';
is there a way to make the function treat the single string argument as if it were the arguments that the programmer inserted into the function....so when you do
j($str),
instead of having the function treat the $str as a single string argument, it fetches the content of the string and treats it as if the programmer wrote j(1,3) instead of j($str)
also this is a rather simple example, but I'd like it to work for even more complicated argument strings involving arrays, multidimensional arrays, associative arrays, array within arrays, as well as string arguments that have commas in it (so just exploding by comma is not really feasible)
also I'd rather not use eval() in the solution
EDIT
Also I'm trying to get this to work on any function not just mine (and not just this specific function which is just a worthless example function) so preferably the operation is to be done outside of the function
call_user_func_array('j', explode(',', $str));
http://www.php.net/call_user_func_array
I have no idea how you want to make this work for "more complex argument strings including arrays of arrays", since it's hard to express those as strings. If you can format whatever string you have into an array though, for example using JSON strings and json_decode, call_user_func_array is your friend.
This should work for a single, comma-separated string:
function j($str){
list($a, $b) = explode(',', $str);
return $a + $b;
}
What do you want to sum in a multi-dimensional array? All of the values?
If yes: You only have to check the type of your argument (e.g. using is_array()) and then iterate through it. When it is multi-dimensional, call your function recursively.
make all parameter but except the first one optional and then use list() and explode() if the first parameter is a string (or contains ,):
function j($a, $b=null){
if(strpos($a,',')!==false){
list($a,$b) = explode(',',$a)
}
return $a + $b;
}
this is just a basic example, but the principle should be clear:
check if one of the arguments is composed of multiple parameters
if so, parse it on your own to get the single parameters
function j($a, $b = 0){ // make second arg optional
if (! $b) { // is second arg specified and not zero
if (strpos($a, ',') !== false){ // has provided first arg a comma
list($first, $second) = explode(',' $a); // yes then get two values from it
return $first + $second; // return the result
}
}
else {
return $a + $b; // two args were passed, return the result
}
}
Now your function will support both formats, with one argument eg:
$str = '1,3'
j($str);
as well as two arguments:
j(5, 10);
This works :)
function f($str, $delimiter = ';')
{
$strargs = explode($delimiter, $str);
$args = array();
foreach($strargs as $item)
eval("\$args[] = " . $item. ";");
// $args contains all arguments
print_r($args);
}
Check it:
f("6;array(8,9);array(array(1,0,8), 5678)");
Most of the answers assume, that everything is nicely separated with coma ",", but it's not always the case. For example there could be different variable types, even strings with coma's.
$values = "123, 'here, is, a, problem, that, can\'t, be, solved, with, explode() function, mkay?'";
This can be handled with eval() and dot's "..." args retrieval in php 7.
function helper_string_args(...$args) {
return $args;
}
$func = "\$values = \\helper_string_args($values);";
try {
eval($func);
} catch (Exception $e) {
var_dump($e);
exit;
}

selecting an array key based on partial string

I have an array and in that array I have an array key that looks like, show_me_160 this array key may change a little, so sometimes the page may load and the array key maybe show_me_120, I want to now is possible to just string match the array key up until the last _ so that I can check what the value is after the last underscore?
one solution i can think of:
foreach($myarray as $key=>$value){
if("show_me_" == substr($key,0,8)){
$number = substr($key,strrpos($key,'_'));
// do whatever you need to with $number...
}
}
I ran into a similar problem recently. This is what I came up with:
$value = $my_array[current(preg_grep('/^show_me_/', array_keys($my_array)))];
you would have to iterate over your array to check each key separately, since you don't have the possibility to query the array directly (I'm assuming the array also holds totally unrelated keys, but you can skip the if part if that's not the case):
foreach($array as $k => $v)
{
if (strpos($k, 'show_me_') !== false)
{
$number = substr($k, strrpos($k, '_'));
}
}
However, this sounds like a very strange way of storing data, and if I were you, I'd check if there's not an other way (more efficient) of passing data around in your application ;)
to search for certain string in array keys you can use array_filter(); see docs
// the array you'll search in
$array = ["search_1"=>"value1","search_2"=>"value2","not_search"=>"value3"];
// filter the array and assign the returned array to variable
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($key){
return(strpos($key,'search_') !== false);
},
// flag to let the array_filter(); know that you deal with array keys
ARRAY_FILTER_USE_KEY
);
// print out the returned array
print_r($foo);
if you search in the array values you can use the flag 0 or leave the flag empty
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value){
return(strpos($value,'value') !== false);
},
// flag to let the array_filter(); know that you deal with array value
0
);
or
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value){
return(strpos($value,'value') !== false);
}
);
if you search in the array values and array keys you can use the flag ARRAY_FILTER_USE_BOTH
$foo = array_filter(
// the array you wanna search in
$array,
// callback function to search for certain sting
function ($value, $key){
return(strpos($key,'search_') !== false or strpos($value,'value') !== false);
},
ARRAY_FILTER_USE_BOTH
);
in case you'll search for both you have to pass 2 arguments to the callback function
You can also use a preg_match based solution:
foreach($array as $str) {
if(preg_match('/^show_me_(\d+)$/',$str,$m)) {
echo "Array element ",$str," matched and number = ",$m[1],"\n";
}
}
filter_array($array,function ($var){return(strpos($var,'searched_word')!==FALSE);},);
return array 'searched_key' => 'value assigned to the key'
foreach($myarray as $key=>$value)
if(count(explode('show_me_',$event_key)) > 1){
//if array key contains show_me_
}
More information (example):
if array key contain 'show_me_'
$example = explode('show_me_','show_me_120');
print_r($example)
Array ( [0] => [1] => 120 )
print_r(count($example))
2
print_r($example[1])
120

Categories