Make str_replace not replace a letter if follows another letter - php

I have a string which contains a math formula, like T + ST + s + t ...
I'm replacing all those letter identifiers with numbers using:
$ids = array(
'T' => $t1,
'ST', => $st,
's', => $s1,
't', => $t2,
'N', => 1,
);
foreach ($ids as $id => $value) {
if (strpos($formula, $id) !== false) {
$formula = str_replace($id, $value, $formula);
}
}
Which is ok in certain situations.
But if the formula has ST at the beginning I get a string like S345324 ..
I fixed this by moving ST in the first position in my array, but I feel it's not really the best option :)
Are there any other "nicer" solutions?

Are you looking for strtr()?
$ids = array(
'T' => $t1,
'ST' => $st,
's' => $s1,
't' => $t2,
'N' => 1,
);
$formula = strtr($formula, $ids);
Note that since strtr() always tries to find the longest possible match, it won't replace occurrences of ST with S$t1 (instead of $st), regardless of how your $replace_pairs array is ordered.
Example (as seen on codepad):
$ids = array(
'T' => 10,
'ST' => 20,
's' => 30,
't' => 40,
'N' => 1,
);
$formula = 'T + ST + s + t';
echo strtr($formula, $ids);
Prints:
10 + 20 + 30 + 40

Related

How can i use the value of the number without the '.' which is generated by thousands_sep?

As you can see I have the thousands_sep with a dot, and "Summe" as the last column obv. is trying to calculate the sum of the rows but it uses 1556€ as 1.556€ thats why i get 234€ instead of 1.788
for ( $a = 0; $a < $i; $a++){
$sum += $tabledata[$a]['value'];
}
$ajaxreturn['beschriftungen'] = $beschriftungen;
$ajaxreturn['chartData'] = $chartdata;
$ajaxreturn['tablehead'] = $tablehead;
$tabledata[(count($tabledata))]= array('category'=>"Summe",'value' => number_format($sum, 0, ',', '.').'€', 'id' => $i);
I tried to change many things but what i need is that the input is "converted" to a number without the '.'
$chartdata[] = array('date' => $iddate, 'value' => round($zeile['summe']), 'id' => $i);
$tabledata[] = array('category' => $beschriftung, 'value' => number_format($zeile['summe'], 0, '', '.').'€', 'id' => $i);
Instead of trying to calculate the sum from the formatted number array ($tabledata), you should calculate the sum alongside the tabledata, like:
$beschriftungen[$iddate] = $beschriftung;
$chartdata[] = array('date' => $iddate, 'value' => round($zeile['summe']), 'id' => $i);
$tabledata[] = array('category' => $beschriftung, 'value' => number_format($zeile['summe'], 0, '', '.').'€', 'id' => $i);
$sum += $zeile['summe'];
Use str_replace('.', '', $value); or even better, preg_replace('/\D/', '', $value). preg_replace will remove also the currency symbol and possible spaces.

str_replace exact match only

Good Day,
I am trying to create a morse code to text and text to morse code converter.
My code:
$letter = str_split(strtolower($_POST['text']));
$morse = $_POST['morse'];
$morsecmp = explode(" ",$morse);
$letter = implode(" ",$letter);
$mode = $_POST['sub'];
$morsecode = array(".-","-...","-.-.","-..","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",
".--.","--.-",".-.","...","-.","..-","...-",".--","-..-","-.--","--..",".");
$letters = array("a","b","c","d","f","g","h","i","j","k","l","m","n","o","p","q","r",
"s","t","u","v","w","x","y","z","e");
if($mode == "Text to Morse Code"){
$letter = str_replace($letters,$morsecode,$letter);
$translated = $letter;
}else{
for($x=0;$x<sizeof($letters);$x++){
for($y=0;$y<sizeof($morsecmp);$y++){
if($morsecode[$x] === $morsecmp[$y]){
echo $morsecode[$x]." === ".$letters[$x]."<br>";
$morse = str_replace($morsecode[$x],$letters[$x],$morse);
}
}
}
$translated = $morse;
}
sample input:
.... . .-.. .-.. --- .-- --- .-. .-.. -..
sample output:
h e ed ed o w o r ed d
expected output:
hello wolrd
My problem is that when converting from morse code to text some characters are not captured properly due to str_replace limit where it will replace all string that is similar to the needle, so if i have to replace all "." to e it will also change "...." which should be actually an h.
any help on this would be greatly appreciated.
Thank You.
Just when you repalce the characters add an extra space for the search string.
$morse = $_POST['morse']." "; // this is to add an extra space at the end of the morse string.
Now we replace all occurrences of morse code strings followed by space with the desired letter.
$morse = str_replace($morsecode[$x]." ",$letters[$x],$morse);
First off, you don't have the full alphabet stored in your array. I noticed you're missing 'e'.
Blow the morse code into an array with explode(' ', $morse_code) and then do a replace on the array (use '/' to delimit words).
Condense it back to a string with implode().
heres an array for you to use, its got the whole alphabet (you can use array_flip to switch the keys and values for translating back and forth)
$translator_table = array(
'A' => '.-',
'B' => '-...',
'C' => '-.-.',
'D' => '-..',
'E' => '.',
'F' => '..-.',
'G' => '--.',
'H' => '....',
'I' => '..',
'J' => '.---',
'K' => '-.-',
'L' => '.-..',
'M' => '--',
'N' => '-.',
'O' => '---',
'P' => '.--.',
'Q' => '--.-',
'R' => '.-.',
'S' => '...',
'T' => '-',
'U' => '..-',
'V' => '...-',
'W' => '.--',
'X' => '-..-',
'Y' => '-.--',
'Z' => '--.',
'0' => '-----',
'1' => '.----',
'2' => '..---',
'3' => '...--',
'4' => '....-',
'5' => '.....',
'6' => '-....',
'7' => '--...',
'8' => '---..',
'9' => '----.',
'.' => '.-.-.-',
',' => '--..--',
'?' => '..--.',
);
The only way to replace exact matches is:
$morse = preg_replace("#{$morsecode[$x]}#", $letters[$x], $morse, 1); //Limit to 1

How to loop an array with strings as indexes in PHP

I had to make an array with as indexes A-Z (the alphabet). Each index had to have a value 0.
So i made this array:
$alfabet = array(
'A' => 0,
'B' => 0,
'C' => 0,
'D' => 0,
'E' => 0,
'F' => 0,
'G' => 0,
'H' => 0,
'I' => 0,
'J' => 0,
'K' => 0,
'L' => 0,
'M' => 0,
'N' => 0,
'O' => 0,
'P' => 0,
'Q' => 0,
'R' => 0,
'S' => 0,
'T' => 0,
'U' => 0,
'V' => 0,
'W' => 0,
'X' => 0,
'Y' => 0,
'Z' => 0
);
I also have got text from a file ($text = file_get_contents('tekst15.txt');)
I have putted the chars in that file to an array: $textChars = str_split ($text);
and sorted it from A-Z: sort($textChars);
What i want is that (with a for loop) when he finds an A in the textChars array, the value of the other array with index A, goes up by one (so like: $alfabet[A]++;
Can anyone help me with this loop? I have this atm:
for($i = 0; $i <= count($textChars); $i++){
while($textChars[$i] == $alfabet[A]){
$alfabet[A]++;
}
}
echo $alfabet[A];
Problem 1: i want to loop the alfabet array to, so now i only check for A but i want to check all indexes.
Problem2: this now returns 7 for each alphabet index i try so its totally wrong :)
I'm sorry about my english but thanks for your time.
Heard of the foreach loop?
foreach ($textChars as $index => $value) {
$alfabet[$value]++;
}
I assume that your $textChars array looks like
$textChars = array (
0 => 'A',
1 => 'A',
2 => 'B',
);
If so you can loop through it and use it's values to check if given index exists in $alfabet and then increment it.
foreach($textChars as $char){
if(isset($alfabet[$char])){
$alfabet[$char]++;
}
}
$fp = fopen('tekst15.txt', 'r');
if (!$fp) {
echo 'Could not open file tekst15.txt';
}
while (false !== ($char = fgetc($fp))) {
if(isset($alfabet[strtoupper($char)]))
{ $alfabet[strtoupper($char)] = $alfabet[strtoupper($char)]+1; }
}
The count_chars() function can give you that information immediately:
$stats = count_chars(file_get_contents('tekst15.txt'));
echo $stats['A']; // number of 'A' occurrences
echo $stats['O']; // number of 'O' occurrences
From your code:
while($textChars[$i] == $alfabet[A]){
$alfabet[A]++;
}
Made no sense at all; it compares each character from the text file to the value of $alfabet[A] which is 0 at first (not even a letter!).
The correct statement would be:
$alfabet[$textChars[$i]]++;

How to remove accent from characters? (Leave only English alphabet glyphs)

I need to transform in PHP, a special character like ă -> a, â -> a, ț -> t and so on.
I need this especially for links, so any help would be appreciated.
When i want to get plain text (from utf-8) i'm using iconv.
iconv('utf8', 'ascii//TRANSLIT', $text);
If it's only for your url, urlencode may be a better idea.
Update the answer from Orlando, I add some more special char
function clean_special_chars ($s, $d=false) {
if($d) $s = utf8_decode( $s );
$chars = array(
'_' => '/`|´|\^|~|¨|ª|º|©|®/',
'a' => '/à|á|ả|ạ|ã|â|ầ|ấ|ẩ|ậ|ẫ|ă|ằ|ắ|ẳ|ặ|ẵ|ä|å|æ/',
'd' => '/đ/',
'e' => '/è|é|ẻ|ẹ|ẽ|ê|ề|ế|ể|ệ|ễ|ë/',
'i' => '/ì|í|ỉ|ị|ĩ|î|ï/',
'o' => '/ò|ó|ỏ|ọ|õ|ô|ồ|ố|ổ|ộ|ỗ|ö|ø/',
'u' => '/ù|ú|û|ũ|ü|ů|ủ|ụ|ư|ứ|ừ|ữ|ử|ự/',
'A' => '/À|Á|Ả|Ạ|Ã|Â|Ầ|Ấ|Ẩ|Ậ|Ẫ|Ă|Ằ|Ắ|Ẳ|Ặ|Ẵ|Ä|Å|Æ/',
'D' => '/Đ/',
'E' => '/È|É|Ẻ|Ẹ|Ẽ|Ê|Ề|Ế|Ể|Ệ|Ễ|Ê|Ë/',
'I' => '/Ì|Í|Ỉ|Ị|Ĩ|Î|Ï/',
'O' => '/Ò|Ó|Ỏ|Ọ|Õ|Ô|Ồ|Ố|Ổ|Ộ|Ỗ|Ö|Ø/',
'U' => '/Ù|Ú|Û|Ũ|Ü|Ů|Ủ|Ụ|Ư|Ứ|Ừ|Ữ|Ử|Ự/',
'c' => '/ć|ĉ|ç/',
'C' => '/Ć|Ĉ|Ç/',
'n' => '/ñ/',
'N' => '/Ñ/',
'y' => '/ý|ỳ|ỷ|ỵ|ỹ|ŷ|ÿ/',
'Y' => '/Ý|Ỳ|Ỷ|Ỵ|Ỹ|Ŷ|Ÿ/'
);
return preg_replace( $chars, array_keys( $chars ), $s );
}
You can use this:
function clean_special_chars( $s, $d=false )
{
if($d) $s = utf8_decode( $s );
$chars = array(
'_' => '/`|´|\^|~|¨|ª|º|©|®/',
'a' => '/à|á|â|ã|ä|å|æ/',
'e' => '/è|é|ê|ë/',
'i' => '/ì|í|î|ĩ|ï/',
'o' => '/ò|ó|ô|õ|ö|ø/',
'u' => '/ù|ú|û|ű|ü|ů/',
'A' => '/À|Á|Â|Ã|Ä|Å|Æ/',
'E' => '/È|É|Ê|Ë/',
'I' => '/Ì|Í|Î|Ĩ|Ï/',
'O' => '/Ò|Ó|Ô|Õ|Ö|Ø/',
'U' => '/Ù|Ú|Û|Ũ|Ü|Ů/',
'c' => '/ć|ĉ|ç/',
'C' => '/Ć|Ĉ|Ç/',
'n' => '/ñ/',
'N' => '/Ñ/',
'y' => '/ý|ŷ|ÿ/',
'Y' => '/Ý|Ŷ|Ÿ/'
);
return preg_replace( $chars, array_keys( $chars ), $s );
}

Sort array string-type keys by a custom alphabet?

I want to sort arrays by key in php, but the alphabet that I'm using is not the normal English alphabet -- it's a self-created alphabet. Is this possible?
My alphabet is:
$alphabet = "AjawbpfmnrhHxXsSqkgtTdD =";
The array is like this:
Array (
[=k_0] => Array(
[0] => DI.3,2 &dwA-nTr& #Hrw#
[1] => mA
[2] => =k
[3] => Sfj,t
[4] => =k
[5] => pXr
)
[aA_2] => Array(
[0] => DI.7,4 &dwA-nTr& #Hrw-smA-tA,wj#
[1] => snD
[2] => aA
[3] => Sfj,t
[4] => jt
[5] => jt,w
)
[sqA_1] => Array(
[0] => DI.6,18 &dwA-nTr& #nswt#
[1] => ra
[2] => sqA
[3] => Sfj,t
[4] => =s
[5] => r
)
);
So if I sort this array following my alphabet then the array with the key [=k_0] should be at the end.
You can use the usort() function and provide your own sorting logic.
See php.net for an example.
Edit: use uksort, not usort. See http://www.php.net/manual/en/function.uksort.php. Thanks #Darien!
A slightly modified example from php.net - the original code with an $alphabet mapping added:
function cmp($a, $b)
{
// custom sort order - just swapps 2 and 3.
$alphabet = array (1 => 1, 2 => 3, 3 => 2, 4 => 4, 5 => 5, 6=> 6);
if ($alphabet[$a] == $alphabet[$b]) {
return 0;
}
return ($alphabet[$a] < $alphabet[$b]) ? -1 : 1;
}
$a = array(3 => 'c' , 2 => 'b', 5 => 'e', 6 => 'f', 1=>'a');
uksort($a, "cmp");
foreach ($a as $key => $value) {
echo "$key: $value\n";
}
Given your $alphabet = "AjawbpfmnrhHxXsSqkgtTdD";, and assuming that A<j<a, etc, per your comment, transform each key in the alternative alphabet to a series in the known alphabet, e.g. use a mapping like:
your alphabet: AjawbpfmnrhHxXsSqkgtTdD
'real'alphabet: abcdefghijklmnopqrstuvw
So the key 'Ajaw' => 'abcd', and 'fmnr' => 'ghij', etc. This then turns your keys into something you can sort using conventional php functions. You'd need some way to handle characeters not present in your original alphabet though.
Something like that might work - you'd need two transform functions (from your alphabet to 'real' alphabet and vice versa), and then a comparator for e.g. uksort.
My two cents - thanks for clarifying the original question.
Fortunately, your custom alphabet does not have more characters than the list of single-byte latin letters, so translating is a very simple and readable process.
I recommend that you set up a translation array before you begin sorting, then translate/normalize the keys for the purpose of sorting.
Code: (Demo)
$array = [
'=k_0' => ['test1'],
'aA_2' => ['test2'],
'sqA_1' => ['test3'],
'=kj_0' => ['test4'],
'awA_2' => ['test5'],
'= D_1' => ['test6'],
'sq A_1' => ['test7'],
'sqA_2' => ['test8'],
];
$trans = ['AjawbpfmnrhHxXsSqkgtTdD =', 'abcdefghijklmnopqrstuvwxy'];
uksort(
$array,
function ($a, $b) use ($trans) {
return strtr($a, ...$trans) <=> strtr($b, ...$trans);
}
);
var_export($array);
Output:
array (
'aA_2' =>
array (
0 => 'test2',
),
'awA_2' =>
array (
0 => 'test5',
),
'sqA_1' =>
array (
0 => 'test3',
),
'sqA_2' =>
array (
0 => 'test8',
),
'sq A_1' =>
array (
0 => 'test7',
),
'=k_0' =>
array (
0 => 'test1',
),
'=kj_0' =>
array (
0 => 'test4',
),
'= D_1' =>
array (
0 => 'test6',
),
)
From PHP7.4, the syntax can be reduced using arrow function syntax.
uksort(
$array,
fn($a, $b) => strtr($a, ...$trans) <=> strtr($b, ...$trans)
);
After feedback from #mickmackusa I have updated my example to work with uksrot and answer the question fully
$order = str_split("AjawbpfmnrhHxXsSqkgtTdD");
uksort($arr, function ($a, $b) use ($order) {
$posA = array_search($a, $order);
$posB = array_search($b, $order);
return $posA - $posB;
});
http://sandbox.onlinephpfunctions.com/code/9b6f39b30dcc932517bbe82608dd8a0c8d35b3da
-- original response with usort--
You can use usort() with a custom order array like so
$arr = array("w","b","m","n","x","x","z","T","T","A","A");
$order = array("A","j","a","w","b","p","f","m","n","r","h","H","x","X","s","S","q","k","g","t","T","d","D"," ","=");
usort($arr, function ($a, $b) use ($order) {
$posA = array_search($a, $order);
$posB = array_search($b, $order);
return $posA - $posB;
});
(you could probably just explode the $order string so it's nicer)
I actually just came across this answer which explains it better, and handles if a value is not inside the order array.
And a working example http://sandbox.onlinephpfunctions.com/code/3934aafe93377ec18549d326d6551608436242a7
<?php
$arr = [8,10,12,18,20,7,4,6,2,20,0]; //take array
$a= sortasc($arr); // call function
function sortasc($arr){
for($i=0;$i<=count($arr);$i++){
for($j=1;$j<=count($arr)-1;$j++){
if($arr[$j-1]>$arr[$j]){
$temp = $arr[$j];
$arr[$j]= $arr[$j-1];
$arr[$j-1] = $temp;
}
}
}
return $arr;
}
?>
See this code:
<?php
$arr = array('wr' => 1, 'wrS' => 6, 'wr,w' => 3, 'wr.w' => 4, 'wr-qA' => 2, 'wrs' => 5);
function compare_by_alphabet(array $alphabet, $str1, $str2)
{
$l1 = strlen($str1);
$l2 = strlen($str2);
$c = min($l1, $l2);
for ($i = 0; $i < $c; $i++)
{
$s1 = $str1[$i];
$s2 = $str2[$i];
if ($s1===$s2) continue;
$i1 = array_search($s1, $alphabet);
if ($i1===false) continue;
$i2 = array_search($s2, $alphabet);
if ($i2===false) continue;
if ($i2===$i1) continue;
if ($i1 < $i2) return -1;
else return 1;
}
if ($l1 < $l2) return -1;
elseif ($l1 > $l2) return 1;
return 0;
}
function compare_keys_by_alphabet($a, $b)
{
static $alphabet = array('-', ',', '.', 'A', 'j', 'a', 'w', 'b', 'p', 'f', 'm', 'n', 'r', 'h', 'H', 'x', 'X', 's', 'S', 'q', '‌​k', 'g', 't', 'T', 'd', 'D', '=', '/', '(', ')', '[', ']', '<', '>', '{', '}', '\'', '*', '#', 'I', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, '&', '#');
return compare_by_alphabet($alphabet, $a, $b);
}
uksort($arr, 'compare_keys_by_alphabet');
print_r($arr);
Result:
Array
(
[wr] => 1
[wr-qA] => 2
[wr,w] => 3
[wr.w] => 4
[wrs] => 5
[wrS] => 6
)

Categories