I have a string that contains 2 informations (1.A Boolean/2.Something(could be number, letter, special chars and could be of any length)).
2 is a user input.
Exemples:
(part 1)"true".(part 2)"321654987" => "true321654987"
Could also be
"false321654987" or "trueweiufv2345fewv"
What I need is a way of parsing trought the string to check first if 1 is true (if its false do nothing), if it is true I need to check if to following part is a positive number higher than 0 (must accepte any number higher than 0 even decimal BUT not bin or hex (well... could be 10 but its would mean ten not two)).
Here is what I tried:
//This part is'nt important it work as it should....
if(isset($_POST['validate']) && $_POST['validate'] == "divSystemePositionnement")
{
$array = json_decode($_POST['array'], true);
foreach($array as $key=>$value)
{
switch($key)
{
case "txtFSPLongRuban":
//This is the important stuff HERE.....
if(preg_match('#^false.*$#', $value))//If false do nothing
{}
else if(!preg_match('#^true[1-9][0-9]*$#', $value))//Check if true and if number higher than 0.
{
//Do stuff,
//Some more stuff
//Just a bit more stuff...
//Done! No more stuff to do.
}
break;
//Many more cases...
}
}
}
As you can see I use regEx to parse trought to string. But it does'nt match decimal number.
I know how to do a regEx to parse decimal this is'nt the question.
The question is:
is there already a function in php that match the parsing I need?
If not, do any of you know a more efficient way to do the parsing or should I just add to my regEx the decimal part?
I was thinking something like :
test = str_split($value, "true")
if(isNumeric(test[1]) && test[1] > 0)
//problem is that isNumeric accepte hex and a cant have letter in there only straight out int or decimal number higher than 0.
Any idea??
Thank you so much for the help!
Use substr : documentation
if(substr($value, 0, 4) == "true"){
$number_part = substr($value, 5);
if(((int) $number == $number) || ((float) $number == $number)){
//do something...
}
}
You can do this:
case "txtFSPLongRuban":
if (preg_match('~^true(?=.*[^0.])([0-9]+(?:\.[0-9]+)?)$~', $value, $match))
{
// do what you want with $match[1] that contains the not null number.
}
break;
The lookahead (?=.*[^0.]) checks if there is somewhere a character that is not a 0 or a .
This oughta do the trick, and handle both types of values:
preg_match('/^(true|false)(.*)$/', $value, $matches);
$real_val = $matches[2];
if ($matches[1] == 'true') {
... true stuff ...
} else if ($matches[1] == 'false') {
... false stuff ...
} else {
... file not found stuff ...
}
Have a try with:
else if(!preg_match('#^true([1-9][0-9]*(?:\.[0-9]*)?$#', $value))
Have a look at ctype_digit:
Checks if all of the characters in the provided string, text, are numerical.
To check for decimals you can use filter_var:
if (filter_var('123.45', FILTER_VALIDATE_FLOAT) !== false) {
echo 'Number';
}
Related
I want to check if a string contains a character repeated zero or more times, for example:
If my string is aaaaaa, bbbb, c or ***** it must return true.
If it contains aaab, cd, or **%*** it must return false.
In other words, if the string has 2 or more unique characters, it must return false.
How to go about this in PHP?
PS: Is there a way to do it without RegEx?
You could split on every character then count the array for unique values.
if(count(array_count_values(str_split('abaaaa'))) == 1) {
echo 'True';
} else {
echo 'false';
}
Demo: https://eval.in/760293
count(array_unique(explode('', string)) == 1) ? true : false;
You can use a regular expression with a back-reference:
if (preg_match('/^(.)\1*$/', $string)) {
echo "Same characters";
}
Or a simple loop:
$same = true;
$firstchar = $string[0];
for ($i = 1; $i < strlen($string); $i++) {
if ($string[$i] != $firstchar) {
$same = false;
break;
}
}
For the fun of it:
<?php
function str2Dec($string) {
$hexstr = unpack('H*', $string);
$hex = array_shift($hexstr);
return hexdec($hex);
}
function isBoring($string) {
return str2Dec($string) % str2Dec(substr($string, 0, 1)) === 0;
}
$string1 = 'tttttt';
$string2 = 'ttattt';
var_dump(isBoring($string1)); // => true
var_dump(isBoring($string2)); // => false
Obviously this works only in small strings because once it gets big enough, the INT will overflow and the mod will not produce the correct value. So, don't use this :) - posting it just to show a different idea from the usual ones.
strlen(str_replace($string[0], '', $string)) ? false : true;
You can check that the number of unique characters is greater than 1. This will perform well even if the input string is empty: (Demo)
$string = 'aaaba';
var_export(
strlen(count_chars($string, 3)) < 2 // false
);
Alternatively, you can trim the string by its first character, but this will generate warnings/notices if the input string has no length. (Demo)
$string = 'aaaba';
var_export(
!strlen(trim($string, $string[0])) // false
);
p.s. Yes, you could use !strlen(trim($string, #$string[0])) to prevent warnings/notices caused by a zero-length string, but I avoid error suppression like the plague because it generally gives code a bad smell.
Regex: ^(.)\1{1,}
^: Starting of string
(.): Match and capture single characted.
\1{1,}: using captured character one or more than once.
For this you can use regex
OR:
PHP code demo
$string="bbbb";
if($length=strlen($string))
{
substr_count($string,$string[0]);
if($length==substr_count($string,$string[0]))
{
echo "Do something";
}
}
I have a simple function which checks if a value is a number and if that number is less than 0.
function check_number($value){
if(!is_numeric(strval($value))){
return "value must be whole or decimal";
} else {
if($value < 0){
return "value must be bigger than 0";
}
}
return "successful value";
}
This functions works all well and good, until special numbers are passed in such as:
0xf4c3b00c
1e7
These values will still make the function return "successful value".
How can I make these special numbers not return a false positive in my case.
Thanks.
function check_number($value){
if (!is_numeric($value)) {
return "That is not a number";
}
if ($value < 0) {
return "value must be bigger than 0";
}
if(!ctype_digit(str_replace('.', '', $value))){
return "value must be whole or decimal";
}
return "successful value";
}
SEE DEMO
You have peculiar requirements. Your definition of a number differs from PHP's - 4.1e7 is a number, just not one formatted in a way you like. So you need to look at the number as it appears - as a string.
Check if value is less than 0 first, because later we won't distinguish between a minus sign and any other character.
Count dots in the number string.
If more than 1 dot, return fail.
If just 1 dot, str_replace it out and continue.
Finally, use ctype_digit on the remaining string.
Change
if(!is_numeric(strval($value))){
into
$value = trim($value, "0"); // get value as string and remove leading and trailing zeroes
$value_float = ltrim(floatval($value), "0"); // get float value as string and remove leading zero
if($value !== $value_float){
or to make it compacter
if(trim($value, "0") !== ltrim(floatval($value), "0")){
to check whether the numerical representation is still the same after stringifying.
Is there a shorthand way of writing the code below?
if (($tstat=='no_prices')&&($l1stat=='no_prices')&&($l2stat=='no_prices')&&($l3stat=='no_prices'))
{
//do something
}
I tried using the below code,but it did something when one of the variables was not equal to 'no_prices'.
if (($tstat && $l1stat && $l2stat && $l3stat)=='no_prices')
{
//do something
}
To check that the strings weren't causing problems I tried substituting 0 for 'no_prices' and 1 for other values, but the result was the same.
array_flip is several times faster than array_unique:
function all_equal($arr, $value) {
return array_keys(array_flip($arr)) == array($value);
}
$arr = array($tstat, $l1stat, $l2stat, $l3stat);
echo all_equal($arr, 'no_prices');
A quick profile for the answers given thus far, for 1000 iterations on array length 1000:
array_flip: 0.07321620 seconds
array_unique: 0.32569408 seconds
foreach: 0.15136194 seconds
array_filter: 0.41404295 seconds
The code used to profile is here: http://codepad.org/szgNfWHe
Note: As #cypherabe rightly points out, array_flip does not overtake array_unique until the array has at least 5 elements, and does not overtake foreach until the array has at least 10 elements.
Unless I'm mistaken, there's no native way of doing this. If this is something that you have to check for often, try using a custom function for it, e.g.:
function allEquals($chkstr, $vals) {
if (!is_array($vals)) { die('allEquals() $vals not an array'); }
foreach ($vals AS $v) {
if ($chkstr != $v) { return false; }
}
return true;
}
My first idea would go into PHP's Array API:
// $tstadt, $l1stat, … are all "no_prices"
$isAllNoPrice = array_unique(array($tstat, $l1stat, …)) == array("no_prices"));
if ($isAllNoPrice) {
// …
}
Documentation is mandatory otherwise nobody (including yourself) will understand the code.
If efficiency might be a concern others pointed out that array_unique() seems to be slow. Using the keys of the hash table would be a next approach:
// $tstadt, $l1stat, … are all "no_prices"
$varsMap = array(
$tstat => null,
$l1stat => null,
// …
);
if (array_keys($varsMap) == array("no_prices")) {
// …
}
But now the wall of code is growing. PHP offers one operator which nearly does what you want and is chainable: &
$v1 = "no_prices";
$v2 = "no_prices";
$v3 = "no_prices";
var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(true)
$v3 = "prices";
var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(false)
I said it nearly does what you want: There are cases in which you will have false positives:
$v1 = 1;
$v2 = 1;
$v3 = 3;
var_dump(($v1 & $v2 & $v3) == 1); // bool(true)
For Strings it seems to cut the bitmask to the shortest string:
$v1 = "abcd";
$v2 = "ab";
$v3 = "abc";
var_dump($v1 & $v2 & $v3); // "ab"
var_dump(($v1 & $v2 & $v3) == "ab"); // bool(true)
So I don't recommend this as a general purpose solution. Only if you know (=unit tested) that your values are in a set where no combination never results to a false positive (e.g. {"dog", "cat", "horse"}) you might consider this solution. I gave it a second thought and must say don't use that at all. Imagine how your colleagues will love you for searching a bug introduced by that method.
In your case you can do:
if (count(array_unique($tstat, $l1stat, $l2stat, $l3stat)) == 1 //Check if all share the same value (i.e., number of unique values is 1
&& $tstat == 'no_prices')) //If everything is the same and $stat == 'no_prices', then everything is 'no_prices'
{
}
<?php
$tstat = $l1stat = $l2stat = $l3stat = 'no_prices';
$testVars = array($tstat,$l1stat,$l2stat,$l3stat);
if(count(array_filter($testVars, function($x) { return $x === 'no_prices'; })) == count($testVars))
{
print("Correct");
}
Use array_filter with a anonymous callback, and check if its length is greater is equal to original array i.e. all conditions passed,
or if length is greater than zero i.e. any one condition passed
No, this code won't work:
if (($tstat&&$l1stat&&$l2stat&&$l3stat)=='no_prices')
{
//do something
}
Why? Because condition in parentheses, will check result itself - You are comparing boolean to string. So in pseudo-code, thats what your code looks like:
if ( ($tstat is true, $l1stat is true, $l2stat is true, $l3stat is true) == 'no_prices' )
^ whole thing returns true ^ ^ true ^
If you wan't to achieve this, you can use count() and array_unique():
if ($tstat == 'no_prices' && count(array_unique(array($tstat, $l1stat, $l2stat, $l3stat))) == 1)
try this:
$arr = array($tstat,$l1stat,...); //make an array
$arr =array_unique($arr);//unique this array
if(count($arr) == 1 && $arr[0] = 'no_prices'){ // check if only one array element have with same value
echo "got it";
}
demo example
The answer is "no". There's no shorthand to the given condition that will make your code more readable, which should be your top priority. You can improve it though:
define('MYAPP_NO_PRICES', 'no_prices');
if ($tstat === MYAPP_NO_PRICES
&& $l1stat === MYAPP_NO_PRICES
&& $l2stat === MYAPP_NO_PRICES
&& $l3stat === MYAPP_NO_PRICES) {
// do something
}
Having all these vars to check individually is a code smell; you might want to rethink this design so you never have to do this.
I use this code in php to detect whether there is five same symbols in a row in the string and execute some code if it does.
function symbolsInRow($string, $limit = 5) {
$regex = '/(.)\1{'.($limit - 1).',}/us';
return 0 == preg_match($regex, $string);
}
Now I need to do the same thing in javascript, but unfortunately I'm not familiar with it enough. How can be this function converted into javascript? The function should return false if it finds 5 same symbols in row in the given string.
Here you go
function symbolsInRow(string, limit) {
// set the parameter to 5 if it is not provided
limit = (limit || 5);
// create a regexp object, initialized with the regex you want. we escape the \ with \\ because it is a special char in javascript strings.
var regex = new RegExp('(.)\\1{'+(limit-1)+',}');
// return false if we find a match (true if no match is found)
return !regex.test(string);
}
the actual test method will return true if it finds a match. So notice the ! which is the not operator inverting the result of the test, since you wanted to return false if it found a sequence.
example at http://www.jsfiddle.net/gaby/aPTAb/
May be not with a regexp:
function symbolsInRow(str, limit, symbol){
return str.split(symbol).length === limit + 1;
}
This should be equivalent:
function symbolsInRow(string, limit) {
limit = (limit || 5) - 1;
return !(new RegExp('(.)\\1{'+limit+'}')).test(string);
}
For five case-sensitive characters in a row, this should work:
function symbolsInRow(string) {
return /(.)\1{4}/.test(string);
}
If you need to match an arbitrary number of repetitions:
function symbolsInRow(string,limit) {
return (new RegExp('(.)\\1{'+limit+'}')).test(string);
}
The standard PHP way to test whether a string $str ends with a substring $test is:
$endsWith = substr( $str, -strlen( $test ) ) == $test
Is this the fastest way?
What Assaf said is correct. There is a built in function in PHP to do exactly that.
substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0;
If $test is longer than $str PHP will give a warning, so you need to check for that first.
function endswith($string, $test) {
$strlen = strlen($string);
$testlen = strlen($test);
if ($testlen > $strlen) return false;
return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}
This method is a tiny bit more memory-expensive, but it is faster:
stripos(strrev($haystack), $reversed_needle) === 0;
This is best when you know exactly what the needle is, so you can hard-code it reversed. If you reverse the needle programmatically, it becomes slower than the earlier method.
Edit (12 years later): LOL, this is a super-old answer that I wrote when I didn't know what I was actually talking about. I'd like the think I've grown since then. #DavidHarkness is right, it is not very efficient in the negative case. Probably much faster to just iterate in reverse and bail early if you really need as much perf as possible. Also, php probably has better ways to do this now. Honestly, I haven't written php in nearly a decade, so I'll leave it up to others now.
$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0
Negative offset "starts counting from the end of the string".
Here’s a simple way to check whether one string ends with another, by giving strpos an offset right where the string should be found:
function stringEndsWith($whole, $end)
{
return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false);
}
Straightforward, and I think this’ll work in PHP 4.
It depends on which sort of efficiency you care about.
Your version uses more memory due to the extra copy from the use of substr.
An alternative version might search the original string for the last occurrence of the substring without making a copy, but would probably be slower due to more testing.
Probably the most efficient way is to do loop char-by-char from the -sterlen(test) position till the end of the string and compare. That's the minimal amount of comparisons you can hope to do and there's hardly any extra memory used.
In PHP 8:
str_ends_with('haystack', 'stack'); // true
str_ends_with('haystack', 'K'); // false
and also:
str_starts_with('haystack', 'hay'); // true
PHP RFC: Add str_starts_with(), str_ends_with() and related functions
Another way would be to use the strrpos function:
strrpos($str, $test) == strlen($str) - strlen($test)
But that’s not faster.
I hope that the below answer may be efficient and also simple:
$content = "The main string to search";
$search = "search";
//For compare the begining string with case insensitive.
if(stripos($content, $search) === 0) echo 'Yes';
else echo 'No';
//For compare the begining string with case sensitive.
if(strpos($content, $search) === 0) echo 'Yes';
else echo 'No';
//For compare the ending string with case insensitive.
if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';
//For compare the ending string with case sensitive.
if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';
Don't know if this is fast or not but for a single character test, these work, too:
(array_pop(str_split($string)) === $test) ? true : false;
($string[strlen($string)-1] === $test) ? true : false;
(strrev($string)[0] === $test) ? true : false;
easiest way to check it via regular expression
for example to check if the mail given is gmail:
echo (preg_match("/#gmail\.com$/","example-email#gmail.com"))?'true':'false';
I'm thinking the reverse functions like strrchr() would help you match the end of the string the fastest.
This is pure PHP, without calling external functions, except for strlen.
function endsWith ($ends, $string)
{
$strLength = strlen ($string);
$endsLength = strlen ($ends);
for ($i = 0; $i < $endsLength; $i++)
{
if ($string [$strLength - $i - 1] !== $ends [$i])
return false;
}
return true;
}
for single-char needle:
if (#strrev($haystack)[0] == $needle) {
// yes, it ends...
}