Can someone help me with algorithm for finding the position of the first occurrence of any number in a string?
The code I found on the web does not work:
function my_offset($text){
preg_match('/^[^\-]*-\D*/', $text, $m);
return strlen($m[0]);
}
echo my_offset('[HorribleSubs] Bleach - 311 [720p].mkv');
The built-in PHP function strcspn() will do the same as the function in Stanislav Shabalin's answer when used like so:
strcspn( $str , '0123456789' )
Examples:
echo strcspn( 'That will be $2.95 with a coupon.' , '0123456789' ); // 14
echo strcspn( '12 people said yes' , '0123456789' ); // 0
echo strcspn( 'You are number one!' , '0123456789' ); // 19
HTH
function my_offset($text) {
preg_match('/\d/', $text, $m, PREG_OFFSET_CAPTURE);
if (sizeof($m))
return $m[0][1]; // 24 in your example
// return anything you need for the case when there's no numbers in the string
return strlen($text);
}
function my_ofset($text){
preg_match('/^\D*(?=\d)/', $text, $m);
return isset($m[0]) ? strlen($m[0]) : false;
}
should work for this. The original code required a - to come before the first number, perhaps that was the problem?
I can do regular expressions but I have to go into an altered state to
remember what it does after I've coded it.
Here is a simple PHP function you can use...
function findFirstNum($myString) {
$slength = strlen($myString);
for ($index = 0; $index < $slength; $index++)
{
$char = substr($myString, $index, 1);
if (is_numeric($char))
{
return $index;
}
}
return 0; //no numbers found
}
Problem
Find the first occurring number in a string
Solution
Here is a non regex solution in javascript
var findFirstNum = function(str) {
let i = 0;
let result = "";
let value;
while (i<str.length) {
if(!isNaN(parseInt(str[i]))) {
if (str[i-1] === "-") {
result = "-";
}
while (!isNaN(parseInt(str[i])) && i<str.length) {
result = result + str[i];
i++;
}
break;
}
i++;
}
return parseInt(result);
};
Example Input
findFirstNum("words and -987 555");
Output
-987
Related
I'm facing an issue with a function that gets a string between two other strings.
function string_between($str, $starting_word, $ending_word) {
$subtring_start = strpos($str, $starting_word);
$subtring_start += strlen($starting_word);
foreach ($ending_word as $a){
$size = strpos($str, $a, $subtring_start) - $subtring_start;
}
return substr($str, $subtring_start, $size);
}
The issue is that the function searches for the first ending_word in the array.
An example will be easier to understand:
$array_a = ['the', 'amen']; // Starting strings
$array_b = [',', '.']; // Ending strings
$str = "Hello, the world. Then, it is over.";
Expected result:
"the world."
Current result:
"the world. Then,"
The function will think that the ending_word is "," because it is the first element met in the array_b. However, the text encounters first the '.' after the "the" starting word.
How can I make sure the function goes through the text and stops at the first element in the $str present in the array_b, whatever the position in the array?
Any idea?
Basically, you need to break outside of your foreach loop when $size > 0
That way it stops looping through your array when it finds the 1st occurrence. Here is the more complete code with other fixes:
function stringBetween($string, $startingWords, $endingWords) {
foreach ($startingWords as $startingWord) {
$subtringStart = strpos($string, $startingWord);
if ($subtringStart > 0) {
foreach ($endingWords as $endingWord){
$size = strpos($string, $endingWord, $subtringStart) - $subtringStart + strlen($endingWord);
if ($size > 0) {
break;
}
}
if ($size > 0) {
return substr($string, $subtringStart, $size);
}
}
}
return null;
}
$startArr = array('the', 'amen'); // Starting strings
$endArr = array('.', ','); // Ending strings
$str = "Hello, the world. Then, it is over.";
echo stringBetween($str, $startArr, $endArr); // the world.
This type of problems are best solved by PCRE regexes, only couple of lines needed in function :
function string_between($str, $starts, $ends) {
preg_match("/(?:{$starts}).*?(?:{$ends})/mi", $str, $m);
return $m[0];
}
Then calling like this :
echo string_between("Hello, the world. Then, it is over.", 'the|amen', ',|\.');
Produces : the world.
The trick,- search to the nearest matching ending symbol is done with regex non-greedy seach, indicated by question symbol in pattern .*?. You can even extend this function to accept arrays as starting/ending symbols, just that case modify function (possibly with implode('|',$arr)) for concatenating symbols into regex grouping formula.
Edited version
This works now. Iterate over your teststrings from first array looking for position of occurance from teststring. If found one then search for the second teststring at startposition from end of first string.
To get the shortest hit I store the position from the second and take the minimum.
You can try it at http://sandbox.onlinephpfunctions.com/code/0f1e5c97da62b4daaf0e49f52271fe288d1cacbb
$array_a =array('the','amen');
$array_b =array(',','.', '#');
$str = "Hello, the world. Then, it is over.";
function earchString($str, $array_a, $array_b) {
forEach($array_a as $test) {
$pos = strpos($str, $test);
if ($pos===false) continue;
$found = [];
forEach($array_b as $test2) {
$posStart = $pos+strlen($test);
$pos2 = strpos($str, $test2, $posStart);
$found[] = ($pos2!==false) ? $pos2 : INF;
}
$min = min($found);
if ($min !== INF)
return substr($str,$pos,$min-$pos) .$str[$min];
}
return '';
}
echo earchString($str, $array_a, $array_b);
I want to write a function that take input as a string and convert alphabets to number and returns the converted numbers, in this way: A(a)=1, B(b)=2, C(c)=3... Z(z)=25 using php
thanks in advance
First, we make everything lowercase.
Then, using the ord function, we get the ascii code, and then substract 'a' from it.
function one_char_map($chr)
{
$chr=strtolower($chr);
return ord($chr)-ord('a');
}
function string_map($str)
{
return implode(array_map('one_char_map',str_split($str)));
}
echo string_map('abcD');//0123
Please try this :
function conv($alph=null){
return (!is_null($alph)?strpos("abcdefghijklmnopqrstuvwxyz", $alph):"Need String");
}
echo "<br /><br />";
echo conv("a");
EDIT :
$str = "abcDefghZ";
$out = "";
for($i=0;$i<strlen($str);$i++){
$out .= conv(strtolower($str[$i]));
}
echo $str."<br />".$out;
If you trying to roll your own hash function: DONT.
If you need to accept other characters from ASCII, use PHP's ord() function.
Try this:
This function returns the position, and optionally accepts a base integer to shift the numbers if you need to.
function alpha_ord($str, $base = 0) {
$pos = stripos(
'abcdefghijklmnopqrstuvwxyz',
$str{0}
);
if ($pos !== FALSE) {
$pos += $base;
}
return $pos;
}
print alpha_ord('A'); // 0
print alpha_ord('Z', 1); // 26
print alpha_ord('Z'); // 25
print alpha_ord('A', 65); // 65
I need a regular expression to find out whether the string prefix to the number (_number) and if there is to get this number
//Valid
if (preg_match('/^([a-zA-Z0-9_])+([_])+([0-9]).html$/i', 'this_is_page_15.html'))
{
$page = 15;
}
//Invalid
if (preg_match('/^([a-zA-Z0-9_])+([_])+([0-9]).html$/i', 'this_is_page15.html')) // return false;
If I'm understanding you correctly, you would probably want some kind of function to do this. preg_match will return a 1 if it finds a match, a 0 if no match is found, and FALSE if there is an error. You need to supply the 3rd parameter $matches to capture the matched strings (details here: http://php.net/manual/en/function.preg-match.php).
function testString($string) {
if (preg_match("/^\w+_(\d+)\.html/",$string,$matches)){
return $matches[1];
} else {
return false;
}
}
So testString('this_is_page_15.html') will return 15, and testString('this_is_page15.html') will return FALSE.
$str = 'this_is_page_15.html';
$page;
if(preg_match('!_\d+!', $str, $match)){
$page = ltrim($match[0], "_");
}else{
$page = null;
}
echo $page;
//output = 15
I don't want to echo string if before string is similar to current string. Let's say our strings are,
$strings = array("software","software","game","antivirus");
My difference function,
function ($val1,$val2) {
similar_text($val1,$val2,$percent);
if ($percent>83) {
// should not echo. But don't know how to do.
}
}
But I don't know how can I do it. I guess it should be with using for each.
Try something like this:
$strings = array("software","software","game","antivirus");
$lastString = '';
foreach ($strings as $string) {
similar_text($lastString, $string, $percent);
if ($percent < 83) {
echo "$string<br />";
$lastString = $string;
}
}
If you don't understand some part of it, leave a comment and I will clarify.
Edit:
I moved the $lastString = $string; inside the condition.
Consider the following list of strings:
$strings = array("software","sofware","sofwart","ofwart","fwart","wart","warts");
Leaving the $lastString assignment outside of the loop would only print software even though lots of the words are very very different software they are not so different from the previous word.
Moving it inside actually gives the output :
software
sofwart
wart
$strings = array("software","software","game","antivirus");
$previous = '';
foreach ($strings as $string) {
if ($string===$previous) {
continue;
} else {
echo $string;
$previous = $string;
}
}
But I think it's better to do it with for like this (it should be faster):
$strings = array("software","software","game","antivirus");
$num = count($strings);
for ($i=0;$i<$num;$i++) {
if ($strings[$i]===$strings[$i-1] && $i!==0) {
continue;
} else {
echo $strings[$i];
}
}
Btw I totally did't get what the $percent means..
An approach using array_filter() (assumes >= 5.3):
$strings = array('software', 'software', 'game', 'antivirus');
$filtered = array_filter($strings, function($curr) {
static $prev;
similar_text($prev, $curr, $percent);
$prev = $curr;
if ($percent < 83) {
return $curr;
}
});
print_r($filtered);
Yields:
Array
(
[0] => software
[2] => game
[3] => antivirus
)
Hope this helps. Actually, I never knew about similar_text() until now. Pretty interesting function. Thanks :)
How would you write a short php function to reverse a string. The function must:
have only one argument
not use the built-in function 'strrev' or 'array_reverse'
not a use a looping construct like 'for', 'foreach' or 'while'.
Quickly scanning down, these all look so long!
function rev($str) {
return $str?rev(substr($str,1)).$str[0]:'';
}
Recursive so obviously doesn't work on strings longer than 100 chars.
Since this sounds like homework question I'll tell you how but you code it yourself.
Turn the string into an array with a cast. Then use one of the array sorting functions that takes a user defined sorting function.
function reverseString($string) {
return shell_exec(sprintf('ruby -e \'puts "%s".reverse\'', preg_replace("/\"/", "\\\"", $string)));
}
Recursive solution:
function sr( $txt ){
return $txt[ strlen( $txt ) - 1 ] . ( ( strlen( $txt ) > 1 )?sr( substr( $txt, 0, strlen($txt)-1 ) ):null) ;
}
echo sr( "abc def ghi jklm" );
Explanation:
return $txt[ strlen( $txt ) - 1 ] // return last byte of string
. // concatenate it with:
(( strlen( $txt ) > 1 ) ? // if there are more bytes in string
sr( substr( $txt, 0, strlen( $txt ) - 1 ) // then with reversed string without last letter
: null ); // otherwise with null
To make it work with zero-length string, another conditional expression was added:
return (strlen($txt))? ($txt[ strlen( $txt ) - 1 ] . ( ( strlen( $txt ) > 1 )?sr( substr( $txt, 0, strlen($txt)-1 ) ):null)):"" ;
<?php
// Reversed string and Number
// For Example :
$str = "hello world. This is john duvey";
$number = 123456789;
$newStr = strrev($str);
$newBum = strrev($number);
echo $newStr;
echo "<br />";
echo $newBum;
OUTPUT :
first : yevud nhoj si sihT .dlrow olleh
second: 987654321`enter code here`
Meets all your requirements but works only in PHP 5.3 or higher. Making it work on others is left as homework.
function reverse($str) {
$i=0;
$j=strlen($str)-1;
start:
if($i>=$j) {
goto done;
}
$tmp = $str[$j];
$str[$j--] = $str[$i];
$str[$i++] = $tmp;
goto start;
done:
return $str;
}
function reverse_string($string) {
if($string !== '')
return substr($string, -1).reverse_string(substr($string, 0, strlen($string)-2));
}
A recursive solution. Feels like something like that is what your teacher is looking for.
function my_strrev ($str) {
$length = strlen($str);
switch ($length) {
case 0: return '';
case 1: return $str; break;
case 2: return $str[1] . $str[0];
default :
return $str[$length-1] . my_strrev(substr($str,1,-1)) . $str[0];
break;
}
}
It swaps the first and the last letter and than makes the same with the rest of the string.
Update:
Inspired by mateusza I created another solution (its fun ;))
function my_strrev2 ($str) {
return $str
? my_strrev2(substr($str, 1)) . $str[0]
: '';
}
It works similar to mateuszas, but this one appends the first character, instead of prepend the last one.
My answer is OOP and uses recursion. Takes care by itself of the recursion limit.
class StringReverser
{
public $reversed_string;
public function __construct ($string) {
$original_recursion_limit = ini_get('pcre.recursion_limit');
$array = str_split($string);
krsort($array);
$i = strlen($string);
ini_set('pcre.recursion_limit', $i+1);
$this->add2string($string, $i, $array);
ini_set('pcre.recursion_limit', $original_recursion_limit);
}
public function reverse() {
return $this->reversed_string;
}
private function add2string ($s, $i, $a) {
if($i) {
$i--;
$this->reversed_string .= $a[$i];
$this->add2string($s, $i,$a, $this->reversed_string);
}
}
}
$string = "Elzo Valugi";
echo $string ."<br>";
$reverser = new StringReverser($string);
echo $reverser->reverse();
<?php
$string="jomon is name my";
for($i=strlen($string);$i>=0;$i--)
{
$char.=$string{$i};
}
echo $char."<br/>";
for($i=0; $i<strlen($char);$i++)
{
if($char[$i+1]==" " || $char[$i+1]=="")
{
for($temp=$i; $temp>=0 && $char[$temp]!=' '; $temp--)
echo $char[$temp];
}
echo " ";
}
?>