replace different sub strings in a string - php

I want to replace different sub-strings with multiple different strings in a string, is there a nicer way to do rather than i do labor work and use
str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
as many times as the number of strings to be replaced?
for example: replace a, b and c with d, e and f respectively in any sample string.
Of course i have a large number of words to change for this i need it.

str_replace() accepts an array for both search and replace parameters, so you can pass several strings in array to search and will be replaced by the corresponding strings in the array passed in replace parameter, like so:
$search = array('a','b','c');
$replace = array('d','e','f');
$res = str_replace($search, $replace, 'a b cool');
echo $res; //echoes 'd e fool'

The usual way of doing this is to supply an array of translations
$xlat = array(
'a' => 'd',
'b' => 'e',
'c' => 'f',
);
and then pass it to str_replace:
$result = str_replace(array_keys($xlat), array_values($xlat), $source);
You can build the array from a SQL query or other source.
You must be careful in case there is an intersection between the source and replacement string sets, or internal matches between source strings, e.g.
'Alpha' => 'Beta',
'Beta' => 'Gamma',
or even more sneaky,
'Alpha' => 'Beta',
'Alphabet' => 'ABCDEFGHIJ',
because internally str_replace employs a loop, and therefore "Base Alpha" would come out as "Base Gamma", and "Alphabet" as "Betabet" instead of "ABCDEFGHIJ". One possible way of coping with this is build $xlat incrementally; if you find that in the new couple 'a' => 'b', 'a' is already in the values of $xlat, you can push it onto $xlat instead of appending. Of course, more complicated sets of keywords (or even the exchange of two or more terms) might not be solvable.
Another way is to do it in two runs: you first generate a $xlat1 array of the form
'a' => '###<UNIQUEID1>###',
'b' => '###<UNIQUEID2>###',
and a second array of the form
'###<UNIQUEID1>###' => 'c',
'###<UNIQUEID2>###' => 'd',
You may "upgrade" the first one-array form to the second with a loop:
// First step, we sort $xlat in order of decreasing key size.
// This ensures that *Alphabet* will be replaced before *Alpha* is ever checked.
// Then we build
foreach($xlat as $from => $to)
{
$id = uniqid();
$xlat1[$from] = $id;
$xlat2[$id] = $to;
}
$temp = str_replace(array_keys($xlat1), array_values($xlat1), $source);
$result = str_replace(array_keys($xlat2), array_values($xlat2), $temp);

Related

How to parse a mostly consistent filename into meaningful parts?

I have filenames like:
1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf
Luckily, the file naming is pretty consistent, but I can't absolutely guarantee that someone didn't use a space where they should have used an underscore.
With this in mind, I want to parse the string and extract the following details:
$project_no = '1234
$series_no = '56
$sheet_no = '78'
$revision = 'D'
$title = 'A Fairly Short Title'
Presently, I use the following to grab this info:
$filename = $_FILES['file']['name'][$i];
$filename = preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
$parts = preg_split( "(_| )", $filename );
$project_no = $parts[0];
$series_no = $parts[1];
$sheet_no = $parts[2];
$revision = end($parts);
$title is simply everything that's left over after removing $parts[0] $parts[1], $parts[2], and end($parts), but how should I express that?
I thought I might be able to use
$title = implode(' ',\array_diff_key($parts, [0,1,2,end($parts)]));
But this doesn't remove the $revision bit at the end...
$title = FLOOR AS PROPOSED D
What am I missing, and am I unnecessarily over-complicating this?
The array_diff_key looks at key comparison of both arrays. end() just moves the internal pointer of the array and is actually useless since the value returned from it can't be used in computing difference between 2 arrays' keys.
Current comparison behaves as
array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,'D'])
which looks key wise as:
array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,3])
Hence, the end result of implode is concatenation of 4,5,6,7 keys' values.
To make the second parameter array values as keys, you can use array_flip to make keys as values and values as keys with the below expression:
$title = implode(' ',\array_diff_key($parts, array_flip([0,1,2,count($parts)-1])));
Demo: https://3v4l.org/J6b5r
I fear you are over-complicating this. I think a single preg_match() call is the most direct way to parse your string.
It looks like you grabbed the regex pattern from https://stackoverflow.com/a/2395905/2943403 to trim the extension from your filename; however, I recommend using a regex function when a single non-regex function serves the same purpose.
pathinfo($filename', PATHINFO_FILENAME)
Now that the extension has been removed, let's move on to the parsing.
Code: (Demo)
$filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
preg_match('~([^ _]+)[ _]([^ _]+)[ _]([^ _]+)[ _](.+)[ _](\S)~', pathinfo($filename, PATHINFO_FILENAME), $m);
var_export([
'project_no' => $m[1],
'series_no' => $m[2],
'sheet_no' => $m[3],
'title' => str_replace('_', ' ', $m[4]),
'revision' => $m[5],
]);
Output:
array (
'project_no' => '1234',
'series_no' => '56',
'sheet_no' => '78',
'title' => 'A FAIRLY SHORT TITLE',
'revision' => 'D',
)
If you are deadset on using preg_split(), then the pattern becomes super simple, but there is a little more mopping up to do.
Code: (Demo)
$filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
$m = preg_split('~ |_~', pathinfo($filename, PATHINFO_FILENAME));
$revision = array_pop($m);
var_export([
'project_no' => $m[0],
'series_no' => $m[1],
'sheet_no' => $m[2],
'title' => implode(' ', array_slice($m, 3)),
'revision' => $revision,
]);
// same output as earlier snippet

Get matches from a preg_replace and use them as an array key

I want to get matches from a String and use them in a array as key to change the value in the string to the value of the array.
If it would be easier to realize, i can change the fantasy tags from %! also to whatever don't have problems in JS/jQuery. This script is for external JS Files and change some variables, which I can't Access from JS/jQuery. So I want to insert them with PHP and send them minified and compressed to the Browser.
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$string = preg_replace('%!(.*?)!%',$array[$1],$string);
echo $string;
You can use array_map with preg_quote to turn the keys of your array into regexes, and then use the values of the array as replacement strings in the array form of preg_replace:
$array = array ( 'abc' => 'Test', 'def' => 'Variable', 'ghi' => 'Change' );
$string ='This is just a %!abc!% String and i wanna %!ghi!% the %!def!%';
$regexes = array_map(function ($k) { return "/" . preg_quote("%!$k!%") . "/"; }, array_keys($array));
$string = preg_replace($regexes, $array, $string);
echo $string;
Output:
This is just a Test String and i wanna Change the Variable
Demo on 3v4l.org

Moving first value and key to the end on an array [duplicate]

This question already has answers here:
How do I move an array element with a known key to the end of an array in PHP?
(4 answers)
Closed 4 years ago.
I have an array that looks something like this:
'array_1' => [
'A' => 'A', 'B' => 'B', 'C' => 'C',
],
I need to shift the first value and key to the end of the array, so it should look like this:
'array_1' => [
'B' => 'B', 'C' => 'C', 'A' => 'A',
],
I've tried to do it like this:
array_push($arr, array_shift($arr));
But the result is this:
'array_1' => [
'B' => 'B', 'C' => 'C', '0' => 'A',
],
The key for value A changed to 0 but i need it ro remain A. Any suggestions?
array_push does not allow you to enter a key.
Therefore you have to use
$arr['key'] = value
First, do a reset(array). This reset the internal pointer to point at the first element
So that when you use key($arr), it will return the first key.
Then use array_shift() to get the first value in the array
Code:
reset($arr)
$arr[key($arr)] = array_shift($arr);
array_push($arr, array_shift($arr));
This removes the first VALUE of $arr, and then adds it to the end of the array as a value, therefore with a numeric key. Since there are no extant numeric keys, it is assigned key 0. Hence your result.
You need to extract the first pair, and push that:
reset($arr);
list($k, $v) = each($arr);
array_shift($arr);
$arr[$k] = $v;
That said... if you're relying on non-numeric key order (or mixed numeric/non-numeric keys), then I fear that your design might be flawed.
A keypair array (a dictionary, or sometimes hash or map) has no key order in most languages and even several representations (most notably, JSON - even if most JSON libraries usually maintain insertion order). Assuming it has might be setting oneself up for a fall.

Array keys get lost as they are considered numeric

Let's say there exists an array:
$array = array(
'1001' => 'a',
'1002' => 'b',
'1003' => 'c',
);
Now let's say someone wants reverse that array:
$array = array_reverse($array);
The problem is, that array_reverse seems to cast all numeric values to integers and then resets the indexes:
0 => 'c' - should be '1003' => 'c'
1 => 'b' - should be '1002' => 'b'
2 => 'a' - should be '1001' => 'a'
What someone may have also tried was this - but without any luck (as expected):
$array[(string) $index] = 'a';
You can even experience this yourself here on codepad.
How can this be solved? Do I have to write my own mapping function, which can handle this or is there any other way?
you just need to use the following code:
array_reverse($array, true)
As per php documentation, to preserve keys you must set 2nd parameter to true

Convert flat array to a delimited string to be saved in the database

What is the best method for converting a PHP array into a string?
I have the variable $type which is an array of types.
$type = $_POST[type];
I want to store it as a single string in my database with each entry separated by | :
Sports|Festivals|Other
Use implode
implode("|",$type);
You can use json_encode()
<?php
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
echo json_encode($arr);
?>
Later just use json_decode() to decode the string from your DB.
Anything else is useless, JSON keeps the array relationship intact for later usage!
json_encode($data) //converts an array to JSON string
json_decode($jsonString) //converts json string to php array
WHY JSON : You can use it with most of the programming languages, string created by serialize() function of php is readable in PHP only, and you will not like to store such things in your databases specially if database is shared among applications written in different programming languages
One of the Best way:
echo print_r($array, true);
No, you don't want to store it as a single string in your database like that.
You could use serialize() but this will make your data harder to search, harder to work with, and wastes space.
You could do some other encoding as well, but it's generally prone to the same problem.
The whole reason you have a DB is so you can accomplish work like this trivially. You don't need a table to store arrays, you need a table that you can represent as an array.
Example:
id | word
1 | Sports
2 | Festivals
3 | Classes
4 | Other
You would simply select the data from the table with SQL, rather than have a table that looks like:
id | word
1 | Sports|Festivals|Classes|Other
That's not how anybody designs a schema in a relational database, it totally defeats the purpose of it.
implode():
<?php
$string = implode('|',$types);
However, Incognito is right, you probably don't want to store it that way -- it's a total waste of the relational power of your database.
If you're dead-set on serializing, you might also consider using json_encode()
This one saves KEYS & VALUES
function array2string($data){
$log_a = "";
foreach ($data as $key => $value) {
if(is_array($value)) $log_a .= "[".$key."] => (". array2string($value). ") \n";
else $log_a .= "[".$key."] => ".$value."\n";
}
return $log_a;
}
Hope it helps someone.
$data = array("asdcasdc","35353","asdca353sdc","sadcasdc","sadcasdc","asdcsdcsad");
$string_array = json_encode($data);
now you can insert this $string_array value into Database
For store associative arrays you can use serialize:
$arr = array(
'a' => 1,
'b' => 2,
'c' => 3
);
file_put_contents('stored-array.txt', serialize($arr));
And load using unserialize:
$arr = unserialize(file_get_contents('stored-array.txt'));
print_r($arr);
But if need creat dinamic .php files with array (for example config files), you can use var_export(..., true);, like this:
Save in file:
$arr = array(
'a' => 1,
'b' => 2,
'c' => 3
);
$str = preg_replace('#,(\s+|)\)#', '$1)', var_export($arr, true));
$str = '<?php' . PHP_EOL . 'return ' . $str . ';';
file_put_contents('config.php', $str);
Get array values:
$arr = include 'config.php';
print_r($arr);
You can use serialize:
$array = array('text' => 'Hello world', 'value' => 100);
$string = serialize($array); // a:2:{s:4:"text";s:11:"Hello world";s:5:"value";i:100;}
and use unserialize to convert string to array:
$string = 'a:2:{s:4:"text";s:11:"Hello world";s:5:"value";i:100;}';
$array = unserialize($string); // 'text' => 'Hello world', 'value' => 100
there are many ways ,
two best ways for this are
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5);
echo json_encode($arr);
//ouputs as
{"a":1,"b":2,"c":3,"d":4,"e":5}
$b = array ('m' => 'monkey', 'foo' => 'bar', 'x' => array ('x', 'y', 'z'));
$results = print_r($b, true); // $results now contains output from print_r
Yet another way, PHP var_export() with short array syntax (square brackets) indented 4 spaces:
function varExport($expression, $return = true) {
$export = var_export($expression, true);
$export = preg_replace("/^([ ]*)(.*)/m", '$1$1$2', $export);
$array = preg_split("/\r\n|\n|\r/", $export);
$array = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [null, ']$1', ' => ['], $array);
$export = join(PHP_EOL, array_filter(["["] + $array));
if ((bool) $return) return $export; else echo $export;
}
Taken here.
If you have an array (like $_POST) and need to keep keys and values:
function array_to_string($array) {
foreach ($array as $a=>$b) $c[]=$a.'='.$b;
return implode(', ',$c);
}
Result like: "name=Paul, age=23, city=Chicago"

Categories