The following is the code
<?php
$id ="202883-202882-202884-0";
$str = implode('-',array_unique(explode('-', $id)));
echo $str;
?>
The result is
202883-202882-202884-0
for $id ="202883-202882-202882-0";, result is 202883-202882-0
I would like to replace the duplicate value with zero, so that the result should be like 202883-202882-0-0, not just remove it.
and for $id ="202883-0-0-0";, result should be 202883-0-0-0. zero should not be replaced, repeating zeros are allowed.
How can I archive that?
More info:
I want to replace every duplicate numbers. Because this is for a product comparison website. There will be only maximum 4 numbers. each will be either a 6 digit number or single digit zero. all zero means no product was selected. one 6 digit number and 3 zero means, one product selected and 3 blank.
Each 6 digit number will collect data from database, I dont want to allow users to enter same number multiple times (will happen only if the number is add with the URL manually.).
Update: I understand that my question was not clear, may be my English is poor.
Here is more explanation, this function is for a smartphone comparison website.
The URL format is sitename.com/compare.html?id=202883-202882-202889-202888.
All three numbers are different smartphones(their database product ID).
I dont want to let users to type in the same product ID like id=202883-202882-202882-202888. It will not display two 202882 results in the website, but it will cause some small issues. The URL will be same without change, but the internal PHP code should consider it as id=202883-202882-202888-0.
The duplicates should be replaced as zero and added to the end.
There will be only 4 numbers separated by "-".
The following examples might clear the cloud!
if pid=202883-202882-202889-202888 the result should be 202883-202882-202889-202888
if pid=202883-202883-202883-202888 the result should be 202888-0-0-0
if pid=202883-202882-202883-202888 the result should be 202883-202882-202888-0
if pid=202882-202882-202882-202882 the result should be 202882-0-0-0
I want to allow only either 6 digit numbers or single digit zero through the string.
if pid=rgfsdg-fgsdfr4354-202883-0 the result should be 202883-0-0-0
if pid=fasdfasd-asdfads-adsfds-dasfad the result should be 0-0-0-0
if pid=4354-45882-445202882-202882 the result should be 202882-0-0-0
It is too complicated for me create, I know there are bright minds out there who can do it much more efficiently than I can.
You can do a array_unique (preserves key), then fill the gaps with 0. Sort by key and you are done :)
+ on arrays will unify the arrays but prioritizes the one on the left.
Code
$input = "0-1-1-3-1-1-3-5-0";
$array = explode('-', $input);
$result = array_unique($array) + array_fill(0, count($array), 0);
ksort($result);
var_dump(implode('-',$result));
Code (v2 - suggested by mickmackusa) - shorter and easier to understand
Fill an array of the size of the input array. And replace by leftover values from array_unique. No ksort needed. 0s will be replaced at the preserved keys of array_unique.
$input = "0-1-1-3-1-1-3-5-0";
$array = explode('-', $input);
$result = array_replace(array_fill(0, count($array), 0), array_unique($array));
var_export($result);
Working example.
Output
string(17) "0-1-0-3-0-0-0-5-0"
Working example.
references
ksort - sort by key
array_fill - generate an array filled with 0 of a certain length
This is another way to do it.
$id = "202883-202882-202882-0-234567-2-2-45435";
From the String you explode the string into an array based on the delimiter which in this case is '-'/
$id_array = explode('-', $id);
Then we can loop through the array and for every unique entry we find, we can store it in another array. Thus we are building an array as we search through the array.
$id_array_temp = [];
// Loop through the array
foreach ($id_array as $value) {
if ( in_array($value, $id_array_temp)) {
// If the entry exists, replace it with a 0
$id_array_temp[] = 0;
} else {
// If the entry does not exist, save the value so we can inspect it on the next loop.
$id_array_temp[] = $value;
}
}
At the end of this operation we will have an array of unique values with any duplicates replaced with a 0.
To recreate the string, we can use implode...
$str = implode('-', $id_array_temp);
echo $str;
Refactoring this, using a ternary to replace the If,else...
$id_array = explode('-', $id);
$id_array_temp = [];
foreach ($id_array as $value) {
$id_array_temp[] = in_array($value, $id_array_temp) ? 0 : $value;
}
$str = implode('-', $id_array_temp);
echo $str;
Output is
202883-202882-0-0-234567-2-0-45435
This appears to be a classic XY Problem.
The essential actions only need to be:
Separate the substrings in the hyphen delimited string.
Validate that the characters in each substring are in the correct format AND are unique to the set.
Only take meaningful action on qualifying value.
You see, there is no benefit to replacing/sanitizing anything when you only really need to validate the input data. Adding zeros to your input just creates more work later.
In short, you should use a direct approach similar to this flow:
if (!empty($_GET['id'])) {
$ids = array_unique(explode('-', $_GET['id']));
foreach ($ids as $id) {
if (ctype_digit($id) && strlen($id) === 6) {
// or: if (preg_match('~^\d{6}$~', $id)) {
takeYourNecessaryAction($id);
}
}
}
I am fairly new to PHP and i appear to have reached a roadblock in my code.I have a variable which contains a sequence of numbers separated by a space. I intend on submitting each number into the database as an individual record. My question is how can i deconstruct the variable into individual integers with the intention of submitting each integer as a new record. Here is my code:
foreach ($domains as $domain)
{
$clicked_domains = array($form_entry->{"domain_$domain->id"});
if($clicked_domains){
foreach($clicked_domains as $final_selection){
if ($final_selection != 0){
echo $final_selection." "; // $final_selection now has the value of 17 20 12
}
}
}
}
I would now like to extract each integer from $final_selection (excluding the spaces) for submission to the DB
Check out explode():
Returns an array of strings, each of which is a substring of string formed by splitting it on boundaries formed by the string delimiter.
You can use explode to create an array of integers, and then just loop through each one.
$integer_array = explode(" ", $final_selection);
foreach($integer_array as $integer) {
//submit $integer
}
I've a variable titled $value as follows :
$value = 5985;
If I echo 05985; it prints 15. I understood that PHP considers this number as octal and prints 15 but I don't want 15 I want leading zero/zeroes prefixed to a value contained in a variable $value.
But I want to make it five or say six digits long. In that case I need to add leading zero/zeroes to the value contained in a variable $value. When I add those leading zeroes and echo the variable $value it should look like as follows :
05985; //If I want five digit number
005985; //If I want six digit number
I searched and tried following approach but it didn't work out.
str_pad($value, 8, '0', STR_PAD_LEFT);
sprintf('%08d', $value);
echo $value;
So can someone please suggest me how to do that?
Thanks.
Sprintf does not directly change the value of its second parameter, it returns the result. Try
$value = sprintf('%08d', $value);
You need to treat it as a string.
$number = '05433';
Echo $number;
Should give you what you want. You can also add a zero like this
$number = '0' . $number;
I'm confused as to how PHP determines whether a variable is a string or an array. It seems to depend on the operators being used.
Here's an example:
<?php
$z1 = "abc";
$out = "";
for ($i = 0; $i < strlen($z1); $i++)
{
// $out[$i] = $z1[$i];
$out = $out.$z1[$i];
}
print $out;
?>
In the above version $out becomes a string (print $z1 shows "abc"). However, if I use the first line $out[$i] = $z1[$i];, $out becomes an array.
Can someone please clarify why this happens, and if its possible to access a string's characters with square brackets without converting the output to an array?
The definition of a string in PHP is considered a set of data writen in linear format (i.e: $var = "username=SmokeyBear05,B-day=01/01/1980";)
An array however is a set of data broken down into several parts. A sort of list format if you will. As an example I've written the data string from before, into an array format...
Array(['username']=>"SmokeyBear05", ['B-day']=>"01/01/1980")
Now strings are generally defined as such: $var="Your String";
Arrays however can be written in three different formats:
$var1 = array('data1','data2','data3');
$var2 = array('part A'=>'data1','part B'=>'data2','part C'=>'data3');
The output of var1 starts the index value at 0. The output of var2 however, sets a custom index value. Now the third way to write an array (least common format) is as such:
$var[0]="data1";
$var[1]="data2";
$var[2]="data3";
This takes more work, but allows you to set the index.
Most web developers working with PHP will set data from an external source as a string to deliver it to another PHP script, and then break it down into an array using the explode() function.
When you define variable $out = "", for loop doesn't understand this variable as string value. If you set $out[$i] value, by default, it was treated as an array.
If you want to get the output result as string value, you can define $out = "a" to make sure it's a string variable.
I have an array of mixed values:
$row = array('Unspecified risk','Yes','8','3','2','13','none','-1,49','-2,51','-1,46','-1,54'); -1,94 -1,55
As you can see it contains text and both negative and positive comma-numbers.
I need to convert the numeric values to the right number format and leave the text values as is.
Now I'm looping over the values:
foreach ($row as $value) {
// If $value is numeric, convert it to the
// right number format for use with MySQL (decimal(10,2))
// If not, leave it be.
}
Two related questions I've investigated but cannot find a suitable solution.
Converting a number with comma as decimal point to float
I need php regular expression for numeric value including "-" and ","
Could anyone provide a practical example?
You don't need to use regular expressions.
use str_replace() as you need to replace the ',' for a '.', and then use intval() or floatval() functions to get the numeric value. You can also use strstr() to look for the '.' and decide if using intval() or floatval()
Example:
$row = array('Unspecified risk', 'Yes', '8', '3', '2', '13', 'none', '-1,49', '-2,51', '-1,46', '-1,54');
function toNumber($target){
$switched = str_replace(',', '.', $target);
if(is_numeric($target)){
return intval($target);
}elseif(is_numeric($switched)){
return floatval($switched);
} else {
return $target;
}
}
$row = array_map('toNumber', $row);
var_dump($row);
We use str_replace() to replace the dot for the comma, this way it's a international notation float, even if it's on string, this way later on we can check if it's numeric with is_numeric() <-- this function is awesome as it detects from a string if it's a number or not, no matter integer or float etc.
We use the is_numeric to check if the value is integer float or text and return the corresponding value using intval() or floatval() (the value without the replace applied will not return as a valid numeric, only after switching the , and . it will return true as numeric).
We use $row = array_map('toNumber', $row); to apply the changes to the array.
Profit xD
$row = array('Unspecified risk','Yes','8','3','2','13','none','-1,49','-2,51','-1,46','-1,54');
foreach($row as $key => $var) {
if(strstr($var, ",") && !is_numeric($var)) {
$var1 = str_replace(",","", $var);
if(is_numeric($var1)) {
$decimal = strstr($var, ',', TRUE);
$digits = str_replace($decimal, "", $var1);
$finalValue = $digits * pow(10,$decimal);
$row[$key] = $finalValue;
}
}
}
echo "<pre>"; print_r($row);
NOTE: This will work for php 5.3 or php 5.3+
I am responding so many years later because I dont find any of the provided solutions reliable enough.
This is a more rigid test if a string contains a float with a comma as decimal separator, and if yes, converts it. Also it removes spaces around the number if needed. It does not really test for malformed numbers.
if( preg_match('/^\s*[0-9\.]*,\d*\s*$/', $str))
return (float)str_replace(",",".",str_replace(".","",trim($str)));
else
return $str ;
If you know a numerical value ALWAYS has a European notation (so 1.234 without a comma should also be coverted to 1234), it should be:
if( preg_match('/^\s*[0-9\.]*,?\d*\s*$/', $str))
return (float)str_replace(",",".",str_replace(".","",trim($str)));
else
return $str ;
If you want a truly rigid test, no malformed numbers (like starting with a thousands separator), and that uses ONLY three digits between thousands separators (not all countries use three, though, like India!):
if( preg_match('/^\s*\d{0,3}((?<=\d)\.\d{3})*,?\d*\s*$/', $str))
return (float)str_replace(",",".",str_replace(".","",trim($str)));
else
return $str ;
And lastly if you want to go even more rigid and also do not want numbers to be able to begin or end with a comma ("1.234," or ",17", which in some cases are considered correct) it becomes
if( preg_match('/^\s*\d{1,3}((?<=\d)\.\d{3})*(,\d+)*\s*$/', $str))
return (float)str_replace(",",".",str_replace(".","",trim($str)));
else
return $str ;
Use is_numeric to test and number_format to format:
foreach ($row as &$value) {
$number = str_replace(',', '.', $value);
if (is_numeric($number)) {
$value = number_format($number, 2, '.', '');
}
}
unset($value);