php allow only one period in a string - php

I have been working on this code for hours and I cant seem to make it work. I have an input field that allows users to submit a price for a certain item. Here is the desired process:
//Get the post it price and only allow numbers and one period|dot
$price = $_POST['price'];
$price = preg_replace('#[^0-9.]#i', '', $_POST['price']);
So I only want to allow one period per string, so if the User inputs 100.00.00, it will correct that and remove the first period and convert it to 10000.00
After this I want to add a comma for every 3rd character as follows:
if the posted price is 10000.00 it will convert it to 10,000.00. Is there any way to accomplish this?

$string = "100.00.00";
$array = explode(".", $string);
$last = array_pop($array);
echo number_format(implode("", $array)) . "." . $last;
http://codepad.viper-7.com/t1WuGK

Related

unique ids are not in sequence in PHP

I want to make a database primary key. I am using PHP uniqid() Function.
uniqid(php,true);
Basically I want to add Student IDs in student table of database
e.g PHP-16-001
In which PHP is 3 character Course ID , 16 is year and 001 is student ID.
I can Add this via "."
$id = "php"."date('Y')".$i;
in which $i is a variable who is incrementing but when I fetch data from database I got
php16001
How can I got all characters?
String concatenation operator in php is '.', so to get your extra '-' characters add them to you string, Check the below code. You should insert your unique id in database as "php-16-001". Make sure your $i variable is a string.
$id = "php-" . date('y-') . $i;
Separate them by some character which you can then split by.
$id = sprintf("php-%s-%s", date('Y'), $i);
To "split" it back to individual chunks use explode
$idParts = explode("-", $string);
A better way to do it:
if($i < 9)
{
$i='00'.$i;
}
$unique_id = "PHP-".date('Y')."-".$i;

Round only int of variable

I am busy with a webshop, and I have an issue:
I display the quantity of the products, and the attribute of the product.
Like:
2,4 cm
2,56 dm
Now I want to Round the numbers of the variable, but if I use:
$qty = round($_product->getBundle_qty());
But if I use: $aantal = $_product->getBundle_qty(); everything works okay, but he doesn't round.
Then the attribute doesn't show anymore ( dm, cm, m ETC)
Can somebody help me?
Is the $_product->getBunlde_qty() actually a double or a float? Or is it just a string? In that case, you can use:
$qty = round(floatval($_product->getBundle_qty()));
Edit:
Now if you want to keep the cm / dm in behind the string we can take the string and explode it at all the spaces, thus creating an array from the string. The last value in this array will be the 'cm' or 'dm' text.
$qtyPieces = explode(" ", $_product->getBundle_qty()); //explode at the space
$qtyPiecesCount = count($qtyPieces); //count all pieces
$qty = round(floatval($_product->getBundle_qty())) . " " . $qtyPieces[$qtyPiecesCount - 1]; //get the last value in the array, count minus 1 because we start counting from 0
Fixed it using explode:
$arr = explode(' ',trim($_product->getBundle_qty()));
echo $arr[1];
It is because the attribute portion is a string.
Round your integers first.
//example:
$qty = round(2.4);
Then add the string attribute back to it.
$value = $qty . "cm";

php str_replace only replacing the 1st value in the needle array

I have been using this function for some time now but this is the 1st time I am having this weird trouble with PHP's str_replace function. Here is my code...
$e2p_perline = explode(',', $e2p_wrd_rplc);
$e2p_words = array();
$e2p_words_2b = array();
$e2p_loopcounter = 0;
foreach($e2p_perline as $line){
$e2p_line_words = explode('-', $line);
$e2p_words[$e2p_loopcounter] = $e2p_line_words[0];
$e2p_words_2b[$e2p_loopcounter] = $e2p_line_words[1];
$e2p_loopcounter++;
}
$e2p_message = str_replace($e2p_words, $e2p_words_2b, $e2p_message);
$e2p_wrd_rplc is a string loaded from the database using get_option() function of wordpress. String data in this format c*sh-cash, v*gra-viagra, s3x-sex,....
$e2p_words is an array filled with the words to be replaced and $e2p_words_2b is an array filled with replacement words.
Lets suppose we have
e2p_words is (c*sh, v*agra, s3x)
e2p_words_2b is (cash, viagra, sex)
Now when I run this, only the 1st word c*sh is replaced with cash. Rest of the e2p_words occurrences in e2p_message stay the same.
I am getting no errors or warnings either.
This works for me :
<?php
$e2p_words = array("c*sh", "v*agra", "s3x");
$e2p_words_2b = array("cash", "viagra", "sex");
$e2p_message = "Get a v*agra, or you'll have to pay c*sh for some real s3x.";
$e2p_message = str_replace($e2p_words, $e2p_words_2b, $e2p_message);
echo $e2p_message;
?>
Output :
Get a viagra, or you'll have to pay cash for some real sex.

Calculating total price from string value in php

I have a e-commerce shop and on the shopping cart page it gives me a separate price for every product, but I need total price.
in order to do that, I need to calculate all these values together and that's fine.
But, what bugs me is that I should calculate the sum of variables that are given in this format:
$455.00
What is the best way to extract the value "455" so I could add it to another value afterwards?
I hope I made myself clear...
Don't use float, but instead use an integer in cent. Floats are not precise (see Floating Point Precision), so the calculation tend to fail if you use floats. That's especially a burden if it is related to payments.
$str = '$455.00';
$r = sscanf($str, '$%d.%d', $dollar, $cent);
if ($r <> 2 or $cent > 99 or $cent < 0 or $dollar > 9999 or $dollar < 0) throw new Exception(sprintf('Invalid string "%s"', $str));
$amountInDollarCents = $dollar * 100 + $cent;
echo $str, ' -> ', $amountInDollarCents;
Demo
If you need only the dollar sign removed, use str_replace. To convert that to int or float, typecast it. However, using float results in non-exact calculations so be careful with it!
$newval = (int)str_replace('$', '', '$455.00');
I think that your ECommerce site only has $ (USD)
$price= substr($string_price,1);
This will convert your string to a float:
$price = (float)substr("$455.00", 1);
echo($price);
For more information, you can see this answer, which has a couple of good links for you in it.
What about the following:
$amount = array();
$amount[0] = '$455.15';
$amount[2] = '$85.75';
$total = 0;
foreach ($amount AS $value) {
$value = str_replace('$', '', $value);
$total += $value;
}
echo $total . "\n";
The cleaning operation is:
$value = str_replace('$', '', $value);
You might want to extract it in a function, especially if you need to use it in more than one place.
Another thing to think about is, why do you have the value in such way? It's a display format and such conversion should be the last to be done, ideally by the template. Maybe, if possible, you should consider to fix the code before, instead of applying a patch like this one.
It really looks like your program is doing it wrong. You should really represent all prices as (double) instead of a string. Then only when you need to show the price to the user you would prepend the $ sign to it, converting it to a string. But your program should really treat prices as numbers and not strings.
If you storing your price in the database as a string "$5.99" then you are really doing it wrong.
It's been a long time since I worked with PHP, so I don't know what the best practice would be for working with currency. One quick method would be to remove "$" and ".", and just add together the resulting as integers.
use str_replace() for instance, and replace "$" and "." with an empty string: http://se2.php.net/manual/en/function.str-replace.php
This will give you the whole sum in cents (thus avoiding some potential rounding problems). You can then divide it by 100 and format it however you like to display the sum as dollars.

Get the two most frequent words within several strings

I have a list of phrases and I want to know which two words occurred the most often in all of my phrases.
I tried playing with regex and other codes and I just cannot find the right way to do this.
Can anyone help?
eg:
I am purchasing a wallet
a wallet for 20$
purchasing a bag
I'd know that
a wallet occurred 2 times
purchasing a occurred 2 times
<?
$string = "I am purchasing a wallet a wallet for 20$ purchasing a bag";
//split string into words
$words = explode(' ', $string);
//make chunks block ie [0,1][2,3]...
$chunks = array_chunk($words, 2);
//remove first array element
unset($words[0]);
//make chunks block ie [0,1][2,3]...
//but since first element is removed , the real block will be [1,2][3,4]...
$alternateChunks = array_chunk($words, 2);
//merge both chunks
$totalChunks = array_merge($chunks,$alternateChunks);
$finalChunks = array();
foreach($totalChunks as $t)
{
//change the inside chunk to pharse using +
//+ can be replaced to space, if neeced
//to keep associative working + is used instead of white space
$finalChunks[] = implode('+', $t);
}
//count the words inside array
$result = array_count_values($finalChunks);
echo "<pre>";
print_r($result);
I hesitate to suggest this, as it's an extremely brute force way to go about it:
Take your string of words, explode it using the explode(" ", $string); command, then run it through a for loop checking every two word combination against every two words in the string.
$string = "I am purchasing a wallet a wallet for 20$ purchasing a bag";
$words = explode(" ", $string);
for ($t=0; $t<count($string); $t++)
{
for ($i=0; $i<count($string); $i++)
{
if (($words[$t] . words[$t+1]) == ($words[$i] . $word[$i+1])) {$count[$words[$i].$words[$i+1]]++}
}
}
So the nested for loop steps in, grabs the first two words, compares them to each other set of two consecutive words, then grabs the next two words and does it again. Every answer will have an answer of at least 1 (it will always match itself) but sorting the resulting array by size will give you the most repeated values.
Note that this will run (n-1)*(n-1) iterations, which could get unwieldy FAST.
Place them all into an array, and access them by the current word index and next word index.
I think this should do the trick. It will grab pairs of words, unless you are at the end of the string, where you'll get only one word.
$str = "I purchased a wallet because I wanted a wallet a wallet a wallet";
$words = explode(" ", $str);
$array_results = array();
for ($i = 0; $i<count($words); $i++) {
if ($i < count($words)-1) {
$pair = $words[$i] . " " . $words[$i+1]; echo $pair . "\n";
// Have to check if the key is in use yet to avoid a notice
$array_results[$pair] = isset($array_results[$pair]) ? $array_results[$pair] + 1 : 1;
}
// At the end of the array, just use a single word
else $array_results[$words[$i]] = isset($array_results[$words[$i]]) ? $array_results[$words[$i]] + 1 : 1;
}
// Sort the results
// use arsort() instead to get the highest first
asort($array_results);
// Prints:
Array
(
[I wanted] => 1
[wanted a] => 1
[wallet] => 1
[because I] => 1
[wallet because] => 1
[I purchased] => 1
[purchased a] => 1
[wallet a] => 2
[a wallet] => 4
)
Update changed ++ to +1 above since it wasn't working when tested...
Try to put it with explode into an array and count the values with array_count_values.
<?php
$text = "whatever";
$text_array = explode( ' ', $text);
$double_words = array();
for($c = 1; $c < count($text_array); $c++)
{
$double_words[] = $text_array[$c -1] . ' ' . $text_array[$c];
}
$result = array_count_values($double_words);
?>
I updated it now to two word version. Does this work for you?
array(9) {
["I am"]=> int(1)
["am purchasing"]=> int(1)
["purchasing a"]=> int(2)
["a wallet"]=> int(2)
["wallet a"]=> int(1)
["wallet for"]=> int(1)
["for 20$"]=> int(1)
["20$ purchasing"]=> int(1)
["a bag"]=> int(1)
}
Since you used the excel tag, I thought I'd give it a shot, and it's actually really easy.
Split string using space as delimiter. Data > Text to Columns... > Delimited > Delimiter: Space. Each word is now in its own cell.
Transpose the result (not strictly required but much easier to visualize). Copy, Edit > Paste Special... > Transpose.
Make cells containing consecutive word pairs. So if your words are in cells B5:B15, cell C5 should be =B5&" "&B6 (and drag down).
Count occurence of each word pair: In cell D5, =COUNTIF($C$5:$C$15,"="&C5), drag down.
Highlight the winner(s). Select C5:D15, Format > Conditional Formatting... > Formula Is =$D5=MAX($D$5:$D$15) and choose e.g. a yellow background.
Note that there is some inefficiency in step 4 because the count of each word pair will be calculated multiple times if that word pair occurs multiple times. If this is a concern, then you can first make a list of unique word pairs using Data > Filter > Advanced Filter... > Unique records only.
An automated VBA solution could easily be crafted by recording a macro of the above followed by some minor editing.
One way to go about it is to use SPLIT or a regex to split the sentences into words and store each into an array. Then take the array and create a dictionary object. When you add a term to the dictionary, if it's already there, add 1 to the .value to tally the count.
Here is some example code (far from perfect as it's just to show the overlying concept) that will take all the string in column A and generate a word frequency list in columns B and C. It's not exactly what you want, but should give you some ideas on how you can go about doing it I hope:
Sub FrequencyList()
Dim vArray As Variant
Dim myDict As Variant
Set myDict = CreateObject("Scripting.Dictionary")
Dim i As Long
Dim cell As range
With myDict
For Each cell In range("A1", cells(Rows.count, "A").End(xlUp))
vArray = Split(cell.Value, " ")
For i = LBound(vArray) To UBound(vArray)
If Not .exists(vArray(i)) Then
.Add vArray(i), 1
Else
.Item(vArray(i)) = .Item(vArray(i)) + 1
End If
Next
Next
range("B1").Resize(.count).Value = Application.Transpose(.keys)
range("C1").Resize(.count).Value = Application.Transpose(.items)
End With
End Sub

Categories