PHP array_map trim + parameters - php

I'm using array_map to trim all my array values but I need to pass a third parameter because I need to more than just trim whitespaces so I'm passing in a third parameter. Basically I want to trim all array values of whitespaces, single quotes, and double quotes.
I have a utility class where I created the function and it looks like this:
public function convertToArray($string, $trim = false) {
$split = explode(",", $string);
if($trim) {
$split = array_map("trim", $split, array(" '\""));
}
return $split;
}
Somehow I can't make this work though. I can still see double quotes in the result even though I followed the answer here.
I even tried
if($trim) {
$split = array_map("trim", $split);
$split = array_map("trim", $split, array("'"));
$split = array_map("trim", $split, array('"'));
}
but I still get the same result.

array_map takes a function that takes only one parameter. If you want to map your array with trim() with subsequent parameters different from the default ones, you have to wrap it with an anonymous function:
$split = array_map(function($item) {
return trim($item, ' \'"');
}, $split);

I think you would need to use an anonymous function for that :)
$split = array_map(function ($value) {
return trim($value, " '\"");
}, $split);
Just because this was exactly the same as the other answer, here is an alternative. This approach could be useful if this is an operation you're going to need in many different places ;)
function trim_spaces_and_quotes($value) {
return trim($value, " '\"");
}
$split = array_map('trim_spaces_and_quotes', $split);

I'd use array_walk, and you just have to append your additional characters to the existing defaults (from the docs):
array_walk($string_arr_to_trim, function (&$v) {
$v = trim($v, " \t\n\r\0\x0B'\"");
});

Related

In comma delimited string is it possible to say "exists" in php

In a comma delimited string, in php, as such: "1,2,3,4,4,4,5" is it possible to say:
if(!/*4 is in string bla*/){
// add it via the .=
}else{
// do something
}
In arrays you can do in_array(); but this isn't a set of arrays and I don't want to have to convert it to an array ....
Try exploding it into an array before searching:
$str = "1,2,3,4,4,4,5";
$exploded = explode(",", $str);
if(in_array($number, $exploded)){
echo 'In array!';
}
You can also replace numbers and modify the array before "sticking it back together" with implode:
$strAgain = implode(",", $exploded);
You could do this with regex:
$re = '/(^|,)' + preg_quote($your_number) + '(,|$)/';
if(preg_match($re, $your_string)) {
// ...
}
But that's not exactly the clearest of code; someone else (or even yourself, months later) who had to maintain the code would probably not appreciate having something that's hard to follow. Having it actually be an array would be clearer and more maintainable:
$values = explode(',', $your_string);
if(in_array((str)$number, $values)) {
// ...
}
If you need to turn the array into a string again, you can always use implode():
$new_string = implode(',', $values);

PHP Spintax Processor

I've been using the recurisve SpinTax processor as seen here, and it works just fine for smaller strings. However, it begins to run out of memory when the string goes beyond 20KB, and it's becoming a problem.
If I have a string like this:
{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!
and I want to have random combinations of the words put together, and not use the technique as seen in the link above (recursing through the string until there are no more words in curly-braces), how should I do it?
I was thinking about something like this:
$array = explode(' ', $string);
foreach ($array as $k=>$v) {
if ($v[0] == '{') {
$n_array = explode('|', $v);
$array[$k] = str_replace(array('{', '}'), '', $n_array[array_rand($n_array)]);
}
}
echo implode(' ', $array);
But it falls apart when there are spaces in-between the options for the spintax. RegEx seems to be the solution here, but I have no idea how to implement it and have much more efficient performance.
Thanks!
You could create a function that uses a callback within to determine which variant of the many potentials will be created and returned:
// Pass in the string you'd for which you'd like a random output
function random ($str) {
// Returns random values found between { this | and }
return preg_replace_callback("/{(.*?)}/", function ($match) {
// Splits 'foo|bar' strings into an array
$words = explode("|", $match[1]);
// Grabs a random array entry and returns it
return $words[array_rand($words)];
// The input string, which you provide when calling this func
}, $str);
}
random("{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!");
random("{This|That} is so {awesome|crazy|stupid}!");
random("{StackOverflow|StackExchange} solves all of my {problems|issues}.");
You can use preg_replace_callback() to specify a replacement function.
$str = "{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Austin}!";
$replacement = function ($matches) {
$array = explode("|", $matches[1]);
return $array[array_rand($array)];
};
$str = preg_replace_callback("/\{([^}]+)\}/", $replacement, $str);
var_dump($str);

array_map with str_replace

Is it possible to use array_map in conjunction with str_replace without calling another function to do the str_replace?
For example:
array_map(str_replace(' ', '-', XXXXX), $myArr);
There is no need for array_map. From the docs: "If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well."
No, it's not possible. Though, if you are using PHP 5.3, you can do something like this:
$data = array('foo bar baz');
$data = array_map(function($value) { return str_replace('bar', 'xxx', $value); }, $data);
print_r($data);
Output:
Array
(
[0] => foo xxx baz
)
Sure it's possible, you just have to give array_map() the correct input for the callback function.
array_map(
'str_replace', // callback function (str_replace)
array_fill(0, $num, ' '), // first argument ($search)
array_fill(0, $num, '-'), // second argument ($replace)
$myArr // third argument ($subject)
);
But for the particular example in the question, as chiborg said, there is no need. str_replace() will happily work on an array of strings.
str_replace(' ', '-', $myArr);
Might be important to note that if the array being used in str_replace is multi-dimensional, str_replace won't work.
Though this doesn't directly answer the question of using array_map w/out calling an extra function, this function may still be useful in place of str_replace in array_map's first parameter if deciding that you need to use array_map and string replacement on multi-dimensional arrays. It behaves the same as using str_replace:
function md_str_replace($find, $replace, $array) {
/* Same result as using str_replace on an array, but does so recursively for multi-dimensional arrays */
if (!is_array($array)) {
/* Used ireplace so that searches can be case insensitive */
return str_ireplace($find, $replace, $array);
}
$newArray = array();
foreach ($array as $key => $value) {
$newArray[$key] = md_str_replace($find, $replace, $value);
}
return $newArray;
}

Fastest way of deleting a value in a comma separated list

I've got a list of names separated by commas (they may contain other characters), or be empty, but generally looking like this:
NameA,NameB,NameC
I need to create a function to delete a name if its present in the list and which restores the comma separated structure.
eg: if NameA is to be deleted, I should end up with:
NameB,NameC
NOT
,NameB,NameC
Similarly for the rest.
This is what I came up with, is there a better solution?
$pieces = explode(",", $list);
$key=array_search($deleteuser, $pieces);
if(FALSE !== $key)
{
unset($pieces[$key]);
}
$list = implode(",", $pieces);
That should work pretty well. You may also be interested in PHP's fgetcsv function.
Doc: http://php.net/manual/en/function.fgetcsv.php
You could use the array_splice function to delete from the array. With offset = array_search($deleteuser, $pieces) and length = 1.
If your application data is so large that you are experiencing a crippling amount of lag, then you may have bigger issues that this snippet of code. It might be time to rethink your data storage and processing from the ground up.
In the meantime, here are some benchmarks when imploding a 5001 element array with commas, then using different techniques to remove value 4999. (speeds actually include the generation of the comma-separate string, but all benchmarks are identical in this regard)
explode() + array_search() + unset() + implode() (demo)System time: ~.009 - .011s
$pieces = explode(",", $list);
if (($key = array_search($deleteuser, $pieces)) !== false) {
unset($pieces[$key]);
}
echo implode(",", $pieces);
explode() + array_search() + array_splice() + implode() (demo)System time: ~.010 - .012s
$pieces = explode(",", $list);
if (($key = array_search($deleteuser, $pieces)) !== false) {
array_splice($pieces, $key, 1);
}
echo implode(",", $pieces);
explode() + foreach() + if() + unset() + break + implode() (demo)System time: ~.011 - .012s
$pieces = explode(",", $list);
foreach ($pieces as $key => $value) {
if ($value == $deleteuser) {
unset($pieces[$key]);
break;
}
}
echo implode(",", $pieces);
(note: if you remove the break, the loop can remove multiple occurrences of the needle)
explode() + array_diff() + implode() (demo)System time: ~.010 - .011s
$pieces = explode(",", $list);
$pieces = array_diff($pieces, [$deleteuser]);
echo implode(",", $pieces);
// or just: echo implode(',', array_diff(explode(",", $list), [$deleteuser]);
explode() + array_filter() + implode() (demo)System time: ~.010 - .013s
$pieces = explode(",", $list);
$pieces = array_filter($pieces, function($v) use ($deleteuser) {
return $v != $deleteuser;
});
echo implode(",", $pieces);
preg_quote() + preg_replace() (demo) (regex demo)System time: ~.007 - .010s
$needle = preg_quote($deleteuser, '/');
echo preg_replace('/,' . $needle . '(?=,|$)|^' . $needle . ',/', '', $list);
// if replacing only one value, declare preg_replace's 4th parameter as 1
Note that if you are using a delimiting character that has a special meaning to the regex engine (like +), then you will need to add a slash before it \+ to escape it and make it literal. This would make the pattern: '/\+' . $needle . '(?=\+|$)|^' . $needle . '\+/'
So while the regex-based snippet proved to be slightly (unnoticeably) faster for my arbitrarily conjured string length, you will need to make your own benchmarks to be sure which is the best performer for your application.
That said, and don't get me wrong I love regex, but the regular expression is going to be the easiest for developers to "get wrong" when it is time to modify the pattern AND I am confident that most devs will agree it has the worst overall comprehensibility.
You could also try a regular expression like this (maybe it can be optimized):
$search = 'NameB';
$list = 'NameA,NameB,NameC';
$list = preg_match('/(^' . $search . ',)|(,' . $search. ')/', '', $list);

PHP: Concatenate array element into string with ',' as the separator

Is there a quick way ( existing method) Concatenate array element into string with ',' as the separator? Specifically I am looking for a single line of method replacing the following routine:
//given ('a','b','c'), it will return 'a,b,c'
private static function ConstructArrayConcantenate($groupViewID)
{
$groupIDStr='';
foreach ($groupViewID as $key=>$value) {
$groupIDStr=$groupIDStr.$value;
if($key!=count($groupViewID)-1)
$groupIDStr=$groupIDStr.',';
}
return $groupIDStr;
}
This is exactly what the PHP implode() function is for.
Try
$groupIDStr = implode(',', $groupViewID);
You want implode:
implode(',', $array);
http://us2.php.net/implode
implode()
$a = array('a','b','c');
echo implode(",", $a); // a,b,c
$arr = array('a','b','c');
$str = join(',',$arr);
join is an alias for implode, however I prefer it as it makes more sense to those from a Java or Perl background (and others).
implode() function is the best way to do this. Additionally for the shake of related topic, you can use explode() function for making an array from a text like the following:
$text = '18:09:00';
$t_array = explode(':', $text);
You can use implode() even with empty delimeter: implode(' ', $value); pretty convenient.

Categories