How can I remove the comma separator from a number
e.g. 40,000 resulting in 40000 in php?
function cleanData($a) {
$a = (int)str_replace( '.', '', $a );
return $a;
}
I've tried using this function only when I compare the result (===) of cleanData($a) with 40000 it doesn't match types?
Try this:
function cleanData($a) {
$a = (int) str_replace( ',', '', $a );
return $a;
}
First of all, you want to replace commas (,), not periods. Second, === checks types as well as value so you must typecast from a string to an integer using (int). You did that part, but you weren't replacing commas so the value was 40, not 40000.
Example:
<?php
var_dump((int) str_replace( '.', '', '40,000')); // int(40)
var_dump((int) str_replace( ',', '', '40,000')); // int(40000)
Related
PHP 7.3.4
When I use
$val = '1,234.00';
echo number_format($val, 2, '.', '');
I get
1 (desired output is 1234.00)
If I do
$val = '1,234.00';
$val = str_replace([',', '$'], '', $val);
echo number_format($val, 2, '.', '');
I get
1234.00
Why doesn't the first one work? What am I missing about the number_format function?
There are 2 important points which need to understand about number_format()
number_format() takes a float as the 1st argument. If string given than convert it in Integer/Float. If found any character in string take the integer part before that character.
return a number with grouped thousands that means a string.
First check the datatype
$a = 1234; // integer
$a = 1234.00; // float
$a = "1234.00"; // string and we can use it as int/float
$a = "1,234.00"; // string but we can't use as int/float because of comma
In first example
$val = '1,234.00';
echo number_format($val, 2, '.', '');
The type of $val is string. So number_format() takes only the int/float part of string and when found any character trim that number. So taking only 1 and you are getting 1.00.
Let's try with
$val = '12,34.00';
echo number_format($val, 2, '.', '');
$val = '12Z34.00'; // also check with this
echo number_format($val, 2, '.', '');
And you will get the result 12.00 for both.You can also check with
$val = 12,34;
echo number_format($val, 2, '.', '');
And you will get
PHP Parse error: syntax error, unexpected ','
That means it not assuming $val as a string. Lets we check with a string without ',' and we will again use number_format() with converted number.
$val = "1234.00";
echo $first = number_format($val, 2, '.', ',');
echo $second = number_format($first, 2, '.', ',');
the output of above example is:
1,234.00
1.00
So $val work like a float number and in $first we are getting a string number and for $second it is separate again with comma and the output is 1.00. So if you have a string with comma, first you need to remove comma from that string then format that using number_format()
I have this array:
$versions = [
'1',
'1.0.2.4',
'1.1.0',
'1.12.547.8'
];
And I want:
$versions = [
'001',
'001.000.002.004',
'001.001.000',
'001.012.547.008'
];
But, if I have this:
$versions = [
'1',
'1.12'
];
I want this:
$versions = [
'01',
'01.12'
];
In other words, each string chunk must have same len of max chunk length considering every chunk throughout the array.
Explanation:
I have an array with variable elements number. Each element is a string containing a variable amount of groups of digits -- each separated by a dot. Each digit group has a variable length. I want to pad each sequence of digits so that all array sub-groups have the same length as the max group length.
In the first example, max length is 3 (longest number: 547), so all groups of final array have 3 digits (001, 000, ...). In the second example, max length is 2 (12), so all groups have 2 digits (01, 01, 12).
My solution:
$max = max(
array_map(
'strlen',
call_user_func_array(
'array_merge',
array_map(
function($row) {
return explode( '.', $row );
},
$versions
)
)
)
);
foreach($versions as &$version)
{
$version = preg_replace(
'/\d*(\d{' . $max . '})/',
'\1',
preg_replace(
'/(\d+)/',
str_repeat('0', $max) . '\1',
$version
)
);
}
Explained:
$tmp = array_map(
function($row) {
return explode('.', $row );
},
$versions
);
$tmp = call_user_func_array('array_merge', $tmp);
$tmp = array_map( 'strlen', $tmp );
$max = max($tmp);
$tmp = preg_replace('/(\d+)/', str_repeat('0', $max ) . '\1', $version );
$version = preg_replace( '/\d*(\d{' . $max . '})/', '\1', $tmp);
Someone have any ideas on how to simplify the process?
Well you can just simplify everything what you already did:
First we can implode() the array into a string and match all numbers with preg_match_all().
To then get the longest number we just use array_map() with strlen() as callback and get the longest number with max().
Then when you know your pad length you can go through your array with preg_replace_callback() and pad your numbers with str_pad().
Code:
<?php
$versions = [ '1', '1.0.2.4', '1.1.0', '1.12.547.8' ];
preg_match_all("/\d+/", implode(".", $versions), $m);
$max = max(array_map("strlen", $m[0]));
$new = preg_replace_callback("/(\d+)/", function($m)use($max){
return str_pad($m[1], $max, "0", STR_PAD_LEFT);
}, $versions);
print_r($new);
?>
My modern take on this task resembles #Rizier123's approach, but should be a little more efficient because it doesn't it doesn't use a preg_match_all() call or iterated strlen() calls to determine the padding length.
My snippet uses a different native function to pad each encountered numeric substring, but it otherwise iterates the array of delimited values in the same way that #Rizier123's snippet does. My preg_replace_callback() technique uses PHP7.4's arrow function syntax and the pattern does not bother using a capture group.
Code: (Demo)
$pad = strlen(
max(
explode(
'.',
implode('.', $versions)
)
)
);
var_export(
preg_replace_callback(
'/\d+/',
fn($m) => sprintf("%0{$pad}d", $m[0]),
$versions
)
);
I have a question variable e.g. "4X9"
how can i split this into 3 different variables, to have an integer 4, integer 9 and string X ?
I tried using
$arr = explode('X', $question);
$before = $arr[0];
$bbefore = str_replace('"', "", $before);
$newBefore =(int)$before;`
and the same for after.
list($before, $x, $after) = str_split(str_replace('"', '', $question));
1) Explode string by character using str_split()
2) Use list() to make assigning them variables clearer
3) If $before and/or $after are integers you can cast them after this line of code
list($before, $x, $after) = str_split(str_replace('"', '', $question));
$before = (int) $before;
$after = (int) $after;
Demo
Let's say I have two strings.
$needle = 'AGUXYZ';
$haystack = 'Agriculture ID XYZ-A';
I want to count how often characters that are in $needle occur in $haystack. In $haystack, there are the characters 'A' (twice), 'X', 'Y' and 'Z', all of which are in the needle, thus the result is supposed to be 5 (case-sensitive).
Is there any function for that in PHP or do I have to program it myself?
Thanks in advance!
You can calculate the length of the original string and the length of the string without these characters. The differences between them is the number of matches.
Basically,
$needle = 'AGUXYZ';
$haystack = 'Agriculture ID XYZ-A';
Here is the part that does the work. In one line.
$count = strlen($haystack) - strlen(str_replace(str_split($needle), '', $haystack));
Explanation: The first part is self-explanatory. The second part is the length of the string without the characters in the $needle string. This is done by replacing each occurrences of any characters inside the $needle with a blank string.
To do this, we split $needle into an array, once character for each item, using str_split. Then pass it to str_replace. It replaces each occurence of any items in the $search array with a blank string.
Echo it out,
echo "Count = $count\n";
you get:
Count = 5
Try this;
function count_occurences($char_string, $haystack, $case_sensitive = true){
if($case_sensitive === false){
$char_string = strtolower($char_string);
$haystack = strtolower($haystack);
}
$characters = str_split($char_string);
$character_count = 0;
foreach($characters as $character){
$character_count = $character_count + substr_count($haystack, $character);
}
return $character_count;
}
To use;
$needle = 'AGUXYZ';
$haystack = 'Agriculture ID XYZ-A';
print count_occurences($needle, $haystack);
You can set the third parameter to false to ignore case.
There's no built-in function that handles character sets, but you simply use the substr_count function in a loop as such:
<?php
$sourceCharacters = str_split('AGUXYZ');
$targetString = 'Agriculture ID XYZ-A';
$occurrenceCount = array();
foreach($sourceCharacters as $currentCharacter) {
$occurrenceCount[$currentCharacter] = substr_count($targetString, $currentCharacter);
}
print_r($occurrenceCount);
?>
There is no specific method to do this, but this built in method can surely help you:
$count = substr_count($haystack , $needle);
edit: I just reported the general substr_count method..in your particular case you need to call it for each character inside $needle (thanks #Alan Whitelaw)
If you are not interested in the character distribution, you could use a Regex
echo preg_match_all("/[$needle]/", $haystack, $matches);
which returns the number of full pattern matches (which might be zero), or FALSE if an error occurred. The solution offered by #thai above should be significantly faster though.
If the character distribution is of any importance, you can use count_chars:
$needle = 'AGUXYZ';
$haystack = 'Agriculture ID XYZ-A';
$occurences = array_intersect_key(
count_chars($haystack, 1),
array_flip(
array_map('ord', str_split($needle))
)
);
The result would be an array with keys being the ASCII values of the character.
You can then iterate over it with
foreach($occurences as $char => $amount) {
printf("There is %d occurences of %s\n", $amount, chr($char));
}
You could still pass the $occurences array to array_sum to calculate the total.
substr_count will get you close. However, it will not do individual characters. So you could loop over each character in $needle and call this function while summing the counts.
There is a PHP function substr_count to count the number of instances of a character in a string. It would be trivial to extend it for multiple characters:
function substr_multi_count ($haystack, $needle, $offset = 0, $length = null) {
$ret = 0;
if ($length === null) {
$length = strlen($haystack) - $offset;
}
for ($i = strlen($needle); $i--; ) {
$ret += substr_count($haystack, $needle, $offset, $length);
}
return $ret;
}
I have a recursive method to overcome this:
function countChar($str){
if(strlen($str) == 0) return 0;
if(substr($str,-1) == "x") return 1 + countChar(substr($str,0,-1));
return 0 + countChar(substr($str,0,-1));
}
echo countChar("xxSR"); // 2
echo countChar("SR"); // 0
echo countChar("xrxrpxxx"); // 5
I'd do something like:
split the string to chars (str_split), and then
use array_count_values to get an array of characters with the respective number of occurrences.
Code:
$needle = 'AGUXYZ';
$string = "asdasdadas asdadas asd asdsd";
$array_chars = str_split($string);
$value_count = array_count_values($array_chars);
for ($i = 0; $i < count($needle); $i++)
echo $needle[$i]. " is occur " .
($value_count[$needle[$i]] ? $value_count[$needle[$i]] : '0')." times";
How can I get the following code to work?
$a = explode('s', $str)[0];
I only see solutions looking like this:
$a = explode('s', $str); $a=$a[0];
As others have said, PHP is unlike JavaScript in that it can't access array elements from function returns.
The second method you listed works. You can also grab the first element of the array with the current(), reset(), or array_pop() functions like so:
$a = current( explode( 's', $str ) ); //or
$a = reset( explode( 's', $str ) ); //or
$a = array_pop ( explode( 's', $str ) );
If you would like to remove the slight overhead that explode may cause due to multiple separations, you can set its limit to 2 by passing two after the other arguments. You may also consider using str_pos and strstr instead:
$a = substr( $str, 0, strpos( $str, 's' ) );
Any of these choices will work.
EDIT Another way would be to use list() (see PHP doc). With it you can grab any element:
list( $first ) = explode( 's', $str ); //First
list( ,$second ) = explode( 's', $str ); //Second
list( ,,$third ) = explode( 's', $str ); //Third
//etc.
That not your style? You can always write a small helper function to grab elements from functions that return arrays:
function array_grab( $arr, $key ) { return( $arr[$key] ); }
$part = array_grab( explode( 's', $str ), 0 ); //Usage: 1st element, etc.
EDIT: PHP 5.4 will support array dereferencing, so you will be able to do:
$first_element = explode(',','A,B,C')[0];
You are correct with your second code-block. explode, and other functions can't return a fully formed array for immediate use,and so you have to set a temporary variable. There may be code in the development tree to do that, but the only way to get the elements you need for now, is the temporary variable.
use current
$a = current(explode('s', $str));
but I found is ugly
You can use this:
$a = array_shift(array_slice(explode("s", $str), 0, 1)));
This is the best way I have found to get a specific element from an array from explode.
Breakdown:
Explode returns an array on delimiter
array_slice($arrayname, $offset, $length) gives you a new array with all items from offset, lenght
array_shift($array) gives you the first (and in this case, the only) item in the array passed to it.
This doesen't look pretty, but does the same as:
$a = explode('s', $str)[0];
There must be a better way to do this, but I have not found it.
Update:
I was investigating this because I wanted to extract a portion of a URL, so i did the following tests:
function urlsplitTest()
{
$url = 'control_panel/deliveryaddress/188/edit/';
$passes = 1000000;
Timer::reset();
Timer::start();
$x =0;
while ($x<$passes) {
$res = array_shift(array_slice(explode("/", $url), 2, 1));
$x++;
}
Timer::stop();
$time = Timer::get();
echo $res.'<br />Time used on: array_shift(array_slice(explode("/", $url), 2, 1)):'.$time;
Timer::reset();
Timer::start();
$x =0;
while ($x<$passes) {
$res = array_get(explode("/", $url), 2);
$x++;
}
Timer::stop();
$time = Timer::get();
echo $res.'<br />Time used on: array_get(explode("/", $url), 2): '.$time;
Timer::reset();
Timer::start();
$x =0;
while ($x<$passes) {
$res = substr($url, 30, -6);
$x++;
}
Timer::stop();
$time = Timer::get();
echo $res.'<br />Time used on: substr($url, 30, -6): '.$time;
}
function array_get($array, $pos) {return $array[$pos];}
The results were as following:
Time used on: array_shift(array_slice(explode("/", $url), 2, 1)):7.897379
Time used on: array_get(explode("/", $url), 2): 2.979483
Time used on: substr($url, 30, -6): 0.932806
In my case i wanted to get the number 188 from the url, and all the rest of the url was static, so i ended up using the substr method, but for a dynamic version where lenth may change, the array_get method above is the fastets and cleanest.