Determine the position of a special character in the string in PHP - php

I have to determine the position of a special character in the string for example:
E77eF/74/VA on 6 and 9 position (counting from 1)
we have '/' so I have to change them to position number -> E77eF6749VA
On MSSQL I could use PATINDEX but I need to use php for this.
It should work for everything except 0-9a-zA-Z
I found strpos() and strrpos() on php.net but I doens't work well for me.
Anyway tries to do something like that?

<?php
$content = 'E77eF/74/VA';
//With this pattern you found everything except 0-9a-zA-Z
$pattern = "/[_a-z0-9-]/i";
$new_content = '';
for($i = 0; $i < strlen($content); $i++) {
//if you found the 'special character' then replace with the position
if(!preg_match($pattern, $content[$i])) {
$new_content .= $i + 1;
} else {
//if there is no 'special character' then use the character
$new_content .= $content[$i];
}
}
print_r($new_content);
?>
Output:
E77eF6749VA

Might not be the most efficient way, but works.
$string = 'E77eF/74/VA';
$array = str_split($string);
foreach($array as $key => $letter){
if($letter == '/'){
$new_string.= $key+1;
}
else{
$new_string.= $letter;
}
}
echo $new_string; // prints E77eF6749VA

Related

PHP - Replacing characters with stars, except when there is a minus

How can I replace a string with stars except the first and the last letter but not a minus in case there is one.
Here for better illustration what I try to get:
From:
url-name
To
u**-***e
This is what I have so far:
function get_starred($str) {
$len = strlen($str);
return substr($str, 0, 1).str_repeat('_', $len - 2).substr($str, $len - 1, 1);
}
You could use the PCRE verbs to skip the first character of a string, last character of a string, and any -s. Like this:
(^.|-|.$)(*SKIP)(*FAIL)|.
https://regex101.com/r/YfrZ8r/1/
PHP example using preg_replace
preg_replace('/(^.|-|.$)(*SKIP)(*FAIL)|./', '*', 'url-name');
https://3v4l.org/0dSPQ
hey try implmenting the following:
function get_starred($str) {
$str_array =str_split($str);
foreach($str_array as $key => $char) {
if($key == 0 || $key == count($str_array)-1) continue;
if($char != '-') $str[$key] = '*';
}
return $str;
}
user3783242 has a great solution - However, if you for some reason do not want to use preg_replace(), you could do the following:
function get_starred($str) {
//make the string an array of letters
$str = str_split($str);
//grab the first letter (This also removes the first letter from the array)
$first = array_shift($str);
//grab the last letter (This also removes the last letter from the array)
$last = array_pop($str);
//loop through leftover letters, replace anything not a dash
//note the `&` sign, this is called a Reference, it means that if the variable is changed in the loop, it will be changed in the original array as well.
foreach($str as &$letter) {
//if letter is not a dash, set it to an astrisk.
if($letter != "-") $letter = "*";
}
//return first letter, followed by an implode of characters, followed by the last letter.
return $first . implode('', $str) . $last;
}
Here is mine:
$string = 'url-name foobar';
function star_replace($string){
return preg_replace_callback('/[-\w]+/i', function($match){
$arr = str_split($match[0]);
$len = count($arr)-1;
for($i=1;$i<$len;$i++) $arr[$i] = $arr[$i] == '-' ? '-' : '*';
return implode($arr);
}, $string);
}
echo star_replace($string);
This works on multiple words.
Output
u**-***e f****r
Sandbox
And it also takes into account puctuation
$string = 'url-name foobar.';
Output
u**-***e f****r.

delete the repetetion letters in a string php

I'm trying to parse a string and delete the adjacent letters that are same. I want to return the count of number of deletions and output the resulted string after the deletions are made. Say I have
$str = "aaabbbcc";
As you can see, you need to do 5 deletions to make the adjacent letters not same. The $output string is "abc" and the number of deletions is five.
function str_deletions ($str)
{
$prev = $str[0];
$length = strlen($str);
$deletions = 0;
$output = "";
for ($i=1 ; $i < $length; $i++)
{
if ($str[$i]== $prev)
{
$deletions++;
$prev = $str[$i]; // not sure here ?
}
}
echo $output; // ?
return $deletions;
}
$str = "aabbcc";
echo str_deletions ($str);
EDIT
This is an interview question, I'm not supposed to use any built-in functions like regex or array_count_values
Thanks for your help !
Here is another regex solution. I use a regex to only match a word character that is repeated, and then remove each consecutive repeating character one by one, which allows me to use &$count argument with preg_replace:
count
If specified, this variable will be filled with the number of replacements done.
The regex is
(\w)(?=\1)
See demo. Note you can replace \w with . to match any character but a newline. OR if you need to match only letters, I suggest using '/(\p{L})(?=\1)/u'
See IDEONE demo:
$str = "aaabbbcc";
$cnt = -1;
$result = preg_replace('/(\w)(?=\1)/', "", $str, -1, $cnt);
echo "Result: " . $result . PHP_EOL . "Deletions: " . $cnt;
Output:
Result: abc
Deletions: 5
Regex solution
This is a much simpler way of doing what you're after using preg_replace():
<?php
function str_deletions($str){
$replaced = preg_replace("/(.)\\1+/", "", $str);
$length = strlen($str) - strlen($replaced);
return array("new_word" => $replaced, "chars_replaced" => $length);
}
$str = "aabbcc";
$string_deletions = str_deletions($str);
echo "New String: " . $string_deletions['new_word'] . "\n";
echo "Chars deleted: " . $string_deletions['chars_replaced'] . "\n";
?>
No inbuilt functions
For the purposes of completion (and since you updated your question with more information to say that we can't use regexes because it's an interview question), here's what I'd do:
Using count_chars():
function str_deletions($str){
$string_data['new_word'] = count_chars($str,3);
$string_data['chars_replaced'] = strlen($str) - strlen($string_data['new_word']);
return $string_data;
}
$str = "aabbcc";
echo str_deletions($str);
Note: in this example count_chars(); will return unique chars in a string, not quite remove duplicates (i.e. "aabbccaa" would still yield "abc" as an output) but your question wasn't clear what the interviewer wanted - whether it was truly a remove duplicate question or a unique char question.
Using array_unique():
Slightly slower and a bit more heavy handed:
function str_deletions($str){
$string_array = array_unique(str_split($str));
foreach($string_array as $string_cur){
$string_data['new_word'] .= $string_cur;
}
$string_data['chars_replaced'] = strlen($str) - strlen($string_data['new_word']);
return $string_data;
}
$str = "aabbcc";
echo str_deletions($str);
Note: It's worth pointing out that if I realised it was an interview question, I wouldn't have provided an answer as doing it for you kind of defeats the purpose. Still, with the amount of answers here now and the fact that I've seen something similar to this in an interview, my hope is someone will learn from these.
The basic algorithm (indeed $prev = $str[$i]; isn't at the good place but you wasn't far):
function str_deletion($str) {
$del = 0;
if (1 < $length = strlen($str)) { // $str has more than 1 char
$prev = $str[0];
$output = $prev;
for ($i=1; $i<$length; $i++) {
if ($prev == $str[$i]) {
$del++;
} else {
$prev = $str[$i]; // when different, change the previous character
$output .= $prev; // and append it to the output
}
}
} else {
$output = $str;
}
echo $output;
return $del;
}
I have changed your function
this is not returning both the output string and number of deletions
function str_deletions ($str)
{
$prev = NULL;
$deletions = 0;
$output = "";
$i=0;
while ($i < strlen($str))
{
if (substr($str,$i,1) == $prev)
{
$deletions++;
//$prev = substr($str,$i,1);/*remove this line, no need here as the same stmnt is there after ifelse*/
}else{
$output.=substr($str,$i,1);
}
$prev = substr($str,$i,1);
$i++;
}
$arr = array(
'output'=>$output,
'deletions'=>$deletions
);
return $arr;
}
$str = "aaabbcc";
print_r(str_deletions ($str));
output for above function call is
Array ( [output] => abc [deletions] => 4 )
Solved with no external function except count;
$str="aaavvvffccca";
$count = strlen($str);
for($i=0;$i<$count;$i++){
$array[]=$str[$i];
}
$del =0;
for($i=0;$i<$count;$i++){
$next=isset($array[$i+1])?$array[$i+1]:null;
if($array[$i]==$next)
{
$del++;
}
else
{
$newarray[]=$array[$i];
}
}
echo "Filter Text:". implode('',$newarray);
echo"Total Deleted:".$del;
The straight forward solution to find out the number of deletions can be
If there are N consecutive same characters delete N-1 out of those N characters.
function str_likes($str)
{
$length = strlen($str);
$del = 0;
for ($i=0 ; $i < $length ; $i++)
{
if ($str[$i] == $str[$i+1])
{
$del++;
}
}
return $del;
}
$str = "aabbccaaa";
echo str_likes($str); //4

Remove words starting with uppercase

I have a string, for example FastFood, how do I remove Food and leave only first word? Also it could be VeryFastFood, then Very should be left, etc.
Some strings may containt 3 uppercase starting letters. I need then only this 3 letters to be left. for example YOUProblem - must be YOU.
Here is a function that can do it for you as well:
function removeUppercase($word){
if(ctype_upper(substr($word,0,3))) //Check for first 3 uppercase and return those
return substr($word,0,3);
for($a=1;$a<strlen($word);$a++){ //Otherwise loop through letters until uppercase is found
if(ctype_upper($word[$a]))
return substr($word,0,$a);
}
return $word;
}
Here is a hackish solution, first thing I could think of
<?php
$string = "VeryFastFood";
$found = false;
$tmp = '';
for($i = 0; $i < strlen($string); ++$i)
{
$char = $string[$i];
if(ctype_upper($char))
{
if($found)
{
break;
}
else
{
$found = true;
}
}
$tmp .= $char;
}
$string = $tmp;
var_dump($string);
preg_match(/^[A-Z]([A-Z]{2}|[A-Z][a-zA-Z]|[a-z]{2})[a-z]*/), $stringToCheck, $matches);
$matches[0] //has your string
Something like this should work.

Capitalize every other letter within exploded array

Initially i had posted a question to find a solution to capitalize every other letter in a string. Thankfully Alex # SOF was able to offer a great solution, however ive been unable to get it to work with an array... To be clear what im trying to do in this case is explode quotes, capitalize every other letter in the array then implode them back.
if (stripos($data, 'test') !== false) {
$arr = explode('"', $data);
$newStr = '';
foreach($arr as $index => $char) {
$newStr .= ($index % 2) ? strtolower($char) : strtoupper($char);
}
$data = implode('"', $arr);
}
Using the anonymous function requires >= PHP 5.3. If not, just make the callback a normal function. You could use create_function(), but it is rather ugly.
$str = '"hello" how you "doing?"';
$str = preg_replace_callback('/"(.+?)"/', function($matches) {
$newStr = '';
foreach(str_split($matches[0]) as $index => $char) {
$newStr .= ($index % 2) ? strtolower($char) : strtoupper($char);
}
return $newStr;
}, $str);
var_dump($str);
Output
string(24) ""hElLo" how you "dOiNg?""
CodePad.
If you want to swap the case, swap the strtolower() and strtoupper() calls.
Is this what you're looking for?
foreach($data as $key => $val)
{
if($key%2==0) $data[$key] = strtoupper($data[$key]);
else $data[$key] = strtolower($data[$key]);
}
Or.... instead of using regular expression you could just not even use the explode method, and go with every other character and capitalize it. Here is an example:
$test = "test code here";
$count = strlen($test);
echo "Count = " . $count . '<br/>';
for($i = 0; $i < $count; $i++)
{
if($i % 2 == 0)
{
$test[$i] = strtolower($test[$i]);
}
else
{
$test[$i] = strtoupper($test[$i]);
}
}
echo "Test = " . $test;
The secret lies in the modulus operator. ;)
Edit: Dang, I just noticed the post above me by Jordan Arsenault already submitted this answer... I got stuck on the regex answer I missed that :-/ sorry Jordan, you were already on point.

How to get position of last letter in a string in php?

Example of a string: "Some text.....!!!!!!!!?????"
Using PHP how would I get the position of the last letter (or even alphanum character) which in this example is the letter t?
You could use preg_match_all with the regular expression \p{L} to find all Unicode letters. With the additional flag PREG_OFFSET_CAPTURE you get also the offsets:
$str = "Some text.....!!!!!!!!?????";
if (preg_match_all('/\p{L}/u', $str, $matches, PREG_OFFSET_CAPTURE) > 0) {
$lastMatch = $matches[0][count($matches[0])-1];
echo 'last letter: '.$lastMatch[0].' at '.$lastMatch[1];
} else {
echo 'no letters found';
}
$s = "Some text.....!!!!!!!!embedded?????";
$words = str_word_count($s,2);
$lastLetterPos = array_pop(array_keys($words)) + strlen(array_pop($words)) - 1;
echo $lastLetterPos;
If you want to allow for alphanum rather than just alpha:
$s = "Some text.....!!!!!!!!embedded21?????";
$words = str_word_count($s,2,'0123456789');
$lastLetterPos = array_pop(array_keys($words)) + strlen(array_pop($words)) - 1;
echo $lastLetterPos;
To add other characters as valid:
$s = "Some text.....!!!!!!!!embedded!!à?????";
$words = str_word_count($s,2,'0123456789ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöùúûüýÿ');
$lastLetterPos = array_pop(array_keys($words)) + strlen(array_pop($words)) - 1;
echo $lastLetterPos;
try substr() ;)
echo substr('abcdef', -1, 1);
It all depends on what you consider a letter, and what you want to do with "Some!!!???text???!!!" for example:
The naive solution would be to iterate from the last position in the string to find the first character you want to keep, then return that. (Or iterate from the beginning to find the first character you want to stop at, then return the one before it.)
Or you can use a regex to match what you want to keep, then take the last match. (Or use a regex replace to remove what you don't want to keep, then take the last character.)
Naive:
<?php
$s = "Some text.....!!!!!!!!?????";
$ary = str_split($s);
$position = 0;
$last = 0;
foreach ($ary as $char) {
if (preg_match("/[a-zA-Z0-9]/", $char)) {
$last = $position;
}
$position += 1;
}
echo $last;
?>
<?php
$str = '"Some text.....!!!!!!!!?????"';
$last = -1;
foreach(range('a', 'z') as $letter)
{
$last = max($last, strripos($str, $letter));
}
echo "$last\n"; // 9
?>
Here is a simple and straight-forward O(n) algorithm.
From the manual for ctype_alpha():
In the standard C locale letters are
just [A-Za-z]
If you need a different locale, you should abstract the function that determines if a character is alpha or not. That way you can keep this algorithm and adapt to varying languages.
function lastAlphaPosition($string) {
$lastIndex = strlen($string)-1;
for ($i = $lastIndex; $i > 0; --$i) {
if (ctype_alpha($string[$i])) {
return $i;
}
}
return -1;
}
$testString = 'Some text.....!!!!!!!!?????';
$lastAlphaPos = lastAlphaPosition($testString);
if ($lastAlphaPos !== -1) {
echo $testString[$lastAlphaPos];
} else {
echo 'No alpha characters found.';
}

Categories