preg_replace() digits to an array item - php

I've got this array:
<?php
$menu = array(
9 => 'pages/contact/',
10 => 'pages/calender/jan/'
//...
);
?>
And I've got a string that looks like this:
$string = "This is a text with a link inside it.";
I want to replace ###9### with pages/contact/.
I've got this:
$string = preg_replace("/###[0-9]+###/", "???", $string);
But I can't use $menu[\\\1]. Any help is appreciated.

There is a solution with preg_replace_callback but you can build an array where searched strings are associated to their replacement strings and then use strtr:
$menu = array(
9 => 'pages/contact/',
10 => 'pages/calender/jan/'
.... );
$keys = array_map(function ($i) { return "###$i###"; }, array_keys($menu));
$rep = array_combine($keys, $menu);
$result = strtr($string, $rep);

For this you need preg_replace_callback(), where you can apply a callback function fore each match, e.g.
$string = preg_replace_callback("/###(\d+)###/", function($m)use($menu){
if(isset($menu[$m[1]]))
return $menu[$m[1]];
return "default";
}, $string);

Related

explode string to multidimensional with regular expression

I have string like this
$string = 'title,id,user(name,email)';
and I want result to be like this
Array
(
[0] => title
[1] => id
[user] => Array
(
[0] => name
[1] => email
)
)
so far I tried with explode function and multiple for loop the code getting ugly and i think there must be better solution by using regular expression like preg_split.
Replace the comma with ### of nested dataset then explode by a comma. Then make an iteration on the array to split nested dataset to an array. Example:
$string = 'user(name,email),office(title),title,id';
$string = preg_replace_callback("|\(([a-z,]+)\)|i", function($s) {
return str_replace(",", "###", $s[0]);
}, $string);
$data = explode(',', $string);
$data = array_reduce($data, function($old, $new) {
preg_match('/(.+)\((.+)\)/', $new, $m);
if(isset($m[1], $m[2]))
{
return $old + [$m[1] => explode('###', $m[2])];
}
return array_merge($old , [$new]);
}, []);
print '<pre>';
print_r($data);
First thanks #janie for enlighten me, I've busied for while and since yesterday I've learnt a bit regular expression and try to modify #janie answer to suite with my need, here are my code.
$string = 'user(name,email),title,id,office(title),user(name,email),title';
$commaBetweenParentheses = "|,(?=[^\(]*\))|";
$string = preg_replace($commaBetweenParentheses, '###', $string);
$array = explode(',', $string);
$stringFollowedByParentheses = '|(.+)\((.+)\)|';
$final = array();
foreach ($array as $value) {
preg_match($stringFollowedByParentheses, $value, $result);
if(!empty($result))
{
$final[$result[1]] = explode('###', $result[2]);
}
if(empty($result) && !in_array($value, $final)){
$final[] = $value;
}
}
echo "<pre>";
print_r($final);

preg_replace, preg_replace_callback and Array to string conversion

I have this code from an app in PHP 5.4 :
$rightKey = preg_replace(array(
"/(_)(\p{L}{1})/eu",
"/(^\p{Ll}{1})/eu"
), array(
"mb_strtoupper('\\2', 'UTF-8')",
"mb_strtoupper('\\1', 'UTF-8')"
), $key);
It didn't work well, because preg_replace is deprecated. I did some researches and turned it into :
$rightKey = preg_replace_callback(array(
"/(_)(\p{L}{1})/u",
"/(^\p{Ll}{1})/u"
), function($m) { return array(
"mb_strtoupper('\\2', 'UTF-8')",
"mb_strtoupper('\\1', 'UTF-8')"
); }, $key);
I changed the function to preg_replace_callback, I removed the "e", and I added a callback.
But now I have :
Array to string conversion
And, I really don't know how to adapt the callback so it works ^^.
Thanks :),
The function must return a string, not an array, it is the same function for every matches:
$key = 'abc _def';
$rightKey = preg_replace_callback(array(
"/_(\p{L})/u",
"/(^\p{Ll})/u"
),
function($m) {
return mb_strtoupper($m[1], 'UTF-8');
},
$key);
echo $rightKey;
Output:
Abc Def

preg_replace to match all but first occurance of something?

I'm looking for a way to replace all but first occurrences of a group or some character.
For example a following random string:
+Z1A124B555ND124AB+A555
1,5,2,4,A,B and + are repeating through out the string.
124, 555 are groups of characters that are also reoccurring.
Now, let's say I want to remove every but first occurrence of 555, A and B.
What regex would be appropriate? I could think of an example replacing all:
preg_replace('/555|A|B/','',$string);
Something like ^ that, but I want to keep the first occurrence... Any ideas?
Are your strings always delimited by plus signs? Do 555, A, and B always occur in the first "group" (delimited by +)?
If so, you can split, replace and then join:
$input = '+Z1A124B555+A124AB+A555';
$array = explode('+', $input, 3); // max 3 elements
$array[2] = str_replace(array('555', 'A', 'B'), '', $array[2]);
$output = implode('+', $array);
ps. No need to use regexes, when we can use a simple str_replace
Use the preg_replace_callback function:
$replaced = array('555' => 0, 'A' => 0, 'B' => 0);
$input = '+Z1A124B555+A124AB+A555';
$output = preg_replace_callback('/555|[AB]/', function($matches) {
static $replaced = 0;
if($replaced++ == 0) return $matches[0];
return '';
}, $input);
This solution could be modified to do what you want: PHP: preg_replace (x) occurrence?
Here is a modified solution for you:
<?php
class Parser {
private $i;
public function parse($source) {
$this->i=array();
return preg_replace_callback('/555|A|B/', array($this, 'on_match'), $source);
}
private function on_match($m) {
$first=$m[0];
if(!isset($this->i[$first]))
{
echo "I'm HERE";
$this->i[$first]=1;
}
else
{
$this->i[$first]++;
}
// Return what you want the replacement to be.
if($this->i[$first]>1)
{
$result="";
}
else
{
$result=$m[0];
}
return $result;
}
}
$sample = '+Z1A124B555ND124AB+A555';
$parse = new Parser();
$result = $parse->parse($sample);
echo "Result is: [$result]\n";
?>
A more generic function that works with every pattern.
function replaceAllButFirst($pattern, $replacement, $subject) {
return preg_replace_callback($pattern,
function($matches) use ($replacement, $subject) {
static $s;
$s++;
return ($s <= 1) ? $matches[0] : $replacement;
},
$subject
);
}

search and replace value in PHP array

I was looking for some standard PHP function to replace some value of an array with other, but surprisingly I haven't found any, so I have to write my own:
function array_replace_value(&$ar, $value, $replacement)
{
if (($key = array_search($ar, $value)) !== FALSE) {
$ar[$key] = $replacement;
}
}
But I still wonder - for such an easy thing there must already be some function for it! Or maybe much easier solution than this one invented by me?
Note that this function will only do one replacement. I'm looking for existing solutions that similarly replace a single occurrence, as well as those that replace all occurrences.
Instead of a function that only replaces occurrences of one value in an array, there's the more general array_map:
array_map(function ($v) use ($value, $replacement) {
return $v == $value ? $replacement : $v;
}, $arr);
To replace multiple occurrences of multiple values using array of value => replacement:
array_map(function ($v) use ($replacement) {
return isset($replacement[$v]) ? $replacement[$v] : $v;
}, $arr);
To replace a single occurrence of one value, you'd use array_search as you do. Because the implementation is so short, there isn't much reason for the PHP developers to create a standard function to perform the task. Not to say that it doesn't make sense for you to create such a function, if you find yourself needing it often.
While there isn't one function equivalent to the sample code, you can use array_keys (with the optional search value parameter), array_fill and array_replace to achieve the same thing:
EDIT by Tomas: the code was not working, corrected it:
$ar = array_replace($ar,
array_fill_keys(
array_keys($ar, $value),
$replacement
)
);
If performance is an issue, one may consider not to create multiple functions within array_map(). Note that isset() is extremely fast, and this solutions does not call any other functions at all.
$replacements = array(
'search1' => 'replace1',
'search2' => 'replace2',
'search3' => 'replace3'
);
foreach ($a as $key => $value) {
if (isset($replacements[$value])) {
$a[$key] = $replacements[$value];
}
}
Try this function.
public function recursive_array_replace ($find, $replace, $array) {
if (!is_array($array)) {
return str_replace($find, $replace, $array);
}
$newArray = [];
foreach ($array as $key => $value) {
$newArray[$key] = recursive_array_replace($find, $replace, $value);
}
return $newArray;
}
Cheers!
$ar[array_search('green', $ar)] = 'value';
Depending whether it's the value, the key or both you want to find and replace on you could do something like this:
$array = json_decode( str_replace( $replace, $with, json_encode( $array ) ), true );
I'm not saying this is the most efficient or elegant, but nice and simple.
What about array_walk() with callback?
$array = ['*pasta', 'cola', 'pizza'];
$search = '*';
$replace = '\*';
array_walk($array,
function (&$v) use ($search, $replace){
$v = str_replace($search, $replace, $v);
}
);
print_r($array);
Based on Deept Raghav's answer, I created the follow solution that does regular expression search.
$arr = [
'Array Element 1',
'Array Element 2',
'Replace Me',
'Array Element 4',
];
$arr = array_replace(
$arr,
array_fill_keys(
array_keys(
preg_grep('/^Replace/', $arr)
),
'Array Element 3'
)
);
echo '<pre>', var_export($arr), '</pre>';
PhpFiddle: http://phpfiddle.org/lite/code/un7u-j1pt
PHP 8, a strict version to replace one string value with another:
array_map(fn (string $value): string => $value === $find ? $replace : $value, $array);
An example - replace value foo with bar:
array_map(fn (string $value): string => $value === 'foo' ? 'bar' : $value, $array);
You can make full string matches without specifying the keys of qualifying values, by calling preg_replace() with a pattern containing start and end of string anchors (^, $). If your search term may contain characters which have a special meaning to the regex engine, then be sure to escape them with preg_quote() to avoid breakage. While regex is not entirely called for, regex offers some very convenient ways to tweak the search term handling. (Demo)
function array_replace_value(&$ar, $value, $replacement)
{
$ar = preg_replace(
'/^' . preg_quote($value, '/') . '$/',
$replacement,
$ar
);
}
I might be more inclined to use array_map() with arrow function syntax so that global variables can be accessed within the custom function scope. (Demo)
$needle = 'foo';
$newValue = 'bar';
var_export(
array_map(fn($v) => $v === $needle ? $newValue : $v, $array)
);
$ar = array(1,2,3,4,5,6,7,8);
$find = array(2,3);
$replace = array(13);
function update_bundle_package($ar,$find,$replace){
foreach ($find as $x => $y) {
///TO REMOVE PACKAGE
if (($key = array_search($y, $ar)) !== false) {
unset($ar[$key]);
}
///TO REMOVE PACKAGE
}
$ar = array_merge($ar, $replace);
}
<b>$green_key = array_search('green', $input); // returns the first key whose value is 'green'
$input[$green_key] = 'apple'; // replace 'green' with 'apple'

Replace string in an array with PHP

How can I replace a sub string with some other string for all items of an array in PHP?
I don't want to use a loop to do it. Is there a predefined function in PHP that does exactly that?
How can I do that on keys of array?
Why not just use str_replace without a loop?
$array = array('foobar', 'foobaz');
$out = str_replace('foo', 'hello', $array);
$array = array_map(
function($str) {
return str_replace('foo', 'bar', $str);
},
$array
);
But array_map is just a hidden loop. Why not use a real one?
foreach ($array as &$str) {
$str = str_replace('foo', 'bar', $str);
}
That's much easier.
This is a very good idea that I found and used successfully:
function str_replace_json($search, $replace, $subject)
{
return json_decode(str_replace($search, $replace, json_encode($subject)), true);
}
It is good also for multidimensional arrays.
If you change the "true" to "false" then it will return an object instead of an associative array.
Source: Codelinks
I am not sure how efficient this is, but I wanted to replace strings in a big multidimensional array and did not want to loop through all items as the array structure is pretty dynamic.
I first json_encode the array into a string.
Replace all the strings I want (need to use preg_replace if there are non-English characters that get encoded by json_encode).
json_decode to get the array back.
function my_replace_array($array,$key,$val){
for($i=0;$i<count($array);$i++){
if(is_array($array[$i])){
$array[$i] = my_replace_array($array[$i],$key,$val);
}else{
$array[$i]=str_replace($key,$val,$array[$i]);
}
}
return $array;
}
With array_walk_recursive()
function replace_array_recursive( string $needle, string $replace, array &$haystack ){
array_walk_recursive($haystack,
function (&$item, $key, $data){
$item = str_replace( $data['needle'], $data['replace'], $item );
return $item;
},
[ 'needle' => $needle, 'replace' => $replace ]
);
}
$base = array('citrus' => array( "orange") , 'berries' => array("blackberry", "raspberry"), );
$replacements = array('citrus' => array('pineapple'), 'berries' => array('blueberry'));
$basket = array_replace_recursive($base, $replacements);
$basket = array_replace($base, $replacements);

Categories