PHP: sum parts of a string without explode() - php

I have some strings in this format 15-37;10-38;5-39;, 5-XXS;45-XS;.
Before the - is the quantity, after the - is the size. ; indicates the start of a new pair.
Without having to explode() the string two times, is there a way I can add all the quantities ?
For example, the total quantities for 15-37;10-38;5-39; will be 30.
Thank you.

try with preg_match()
$str ='15-37;10-38;5-39;';
preg_match_all('/(?P<digit>\d+)-/', $str, $matches);
or
preg_match_all('/(\d+)-/', $str, $matches);
echo array_sum($matches[0]); //30

I figured out the following code:
$helper = "15-37;10-38;5-39;";
$sum=0;
for($i=0; $i<$helper.length; $i++){
if($helper[$i]=="-"){
while($helper[$i]!=";")
$i++;
}
else
{
if($helper[$i]!=";"){
$aux="";
while($helper[$i]!="-" && $helper[$i]!=";"){
$aux = $aux.$helper[$i];
//echo $helper[$i]." ";
$k++;
$i++;
}
$i--;
echo (int)$aux."<br>";
$sum = $sum + intval($aux);
}
}
}
echo $sum;
You can test it here: http://writecodeonline.com/php/
The last outputed number is the sum.
Hope it helps!

Related

How to compare 2 numeric strings

I have 2 strings like this
$s1="32.56.86.90.23";
$s2="11.25.32.90.10";
I need to compare $s1 and $s2 and find if there are 2 or more numbers in common.
I am using this way
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
$result=array_diff($s1_ar,$s2_ar);
$rt1=5-count($result);
if($result>=2){ echo "YES"; } else {echo "no"; }
Since I need millions values of $s1 and $s2 and the code above seems to be slow, do you know alternative way to execute the work faster ?
I tested it with the following code, one million times, less than 2 seconds on my 3 years old laptop.
Loop 1M times takes no time, most time is used for displaying.
Comment off the display, 1M loops, 0.816432 seconds
Saved the results into a file, ~13.564MB, 0.731708 seconds
ob_start();
$t1 = microtime();
for($i=1; $i<=1000000; $i++) {
$s1="32.56.86.90.23";
$s2="10.25.30.90.10";
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
$result=array_diff($s1_ar,$s2_ar);
$rt1=5-count($result);
if($result>=2){ echo $i . " YES<br>"; } else {echo $i . " no<br>"; }
}
$out = ob_get_contents();
ob_end_clean();
var_dump($out);
echo '<p>'.(microtime() - $t1).'</p>';
Try this.
$s1="32.56.86.90.23";
$s2="11.23.32.90.10";
$s1_ar=explode(".",$s1);
$s2_ar=explode(".",$s2);
//assuming $s1_ar and $s2_ar both has unique values if not please make them unique
$result_array = array();
$hasMatch = 0;
for($i = 0; $i < count($s1_ar) && $i < count($s2_ar); $i++){
if(!isset($result_array[$s1_ar[$i]])){
$result_array[$s1_ar[$i]] = 1;
}else{
$result_array[$s1_ar[$i]]++;
}
if(!isset($result_array[$s2_ar[$i]])){
$result_array[$s2_ar[$i]] = 1;
}else{
$result_array[$s2_ar[$i]]++;
}
}
foreach($result_array as $result){
if($result >=2) $hasMatch++;
}
if($hasMatch >= 2)
echo "YES";
else
echo "NO";
I think it will solve your purpose.
Looking at: php array_intersect() efficiency
There's mention that array_intersect_key may be more efficient. But really it would be nice to have data and versions to compare results.
$s1 = "2.3.5.7.9.11.13.17";
$s2 = "2.3.4.5.6";
$s1 = array_flip(explode('.', $s1));
$s2 = array_flip(explode('.', $s2));
echo count(array_intersect_key($s1, $s2))>=2 ? 'yes' : 'no';
Output:
yes
I thought of a way to solve this in a 2*n complexity:
We loop one list and create an associative array from it's elements (LIST c) then we loop the second list and look up if the list c contains such an index/key ( c[element] ).
This shall be very light weighted :
$commons = 0;
$s1_fliped = array_flip($s1_ar)
foreach($s2_ar as $s2_el){
if ( isset($s1_fliped[$s2_el]) ){
$commons ++;
}
if($commons >=2) break;
});

php regex matching issue

I have this kind of output:
1342&-4&-6
And it could be more times or less:
1342&-4 (I need to replace it with: 1342,1344)
1340&-1&-3&-5&-7 (I need to replace it with: 1340,1341,1343,1345,1347)
I've tried to use preg_match but with no success,
Can someone help me with that?
Thanks,
<?php
//so if you had sting input of "1342&-4" you would get 2 stings returned "1342" and "1344"?
//1340&-1&-3&-5&-7 --> 1340 and 1341 and 1343 and 1345 and 1347
//$str="1342&-4";
$str="1340&-1&-3&-5&-7";
$x=explode('&-',$str);
//print_r($x);
foreach ($x as $k=> $v){
if($k==0){
//echo raw
echo $v."<br>";
}else{
//remove last number add new last number
echo substr($x[0], 0, -1).$v."<br>";
}
}
output:
13401341134313451347
i used <br> you can use what ever you need or add to a new variable(array)
$array = explode('&-', $string);
$len = count($array);
for($i=1; $i<$len; $i++)
$array[$i] += $array[0] / 10 * 10;
var_dump(implode(' ', $array));

Replacing random numbers in a php string serial numbers(123...)

In PHP, how to convert a string containing mixture of random letters and numbers to a string containing serial numbers along with random numbers without changing their position in a string? For example,
$str_a = "1)Apple 5)Ball 3)Cat 8)Dog 4)Egg";
Now, I want to convert this string into
$str_b = "1)Apple 2)Ball 3)Cat 4)Dog 5)Egg";
I want the numbers 1,5,3,8,4 to be 1,2,3,4,5.
This should work for you:
Just use preg_replace_callback() and replace each digit (\d+ => 0-9 as many times as possible) with an incrementing number, .e.g
<?php
$str_a = "1)Apple 5)Ball 3)Cat 8)Dog 4)Egg";
$start = 1;
echo $newStr = preg_replace_callback("/\d+/", function($m)use(&$start){
return $start++;
}, $str_a);
?>
output:
1)Apple 2)Ball 3)Cat 4)Dog 5)Egg
Created Simple looping program:
$str_a = "1)Apple 5)Ball 3)Cat 8)Dog 4)Egg";
function change($str_a) {
$counter = 1;
for($i=0; $i<strlen($str_a); $i++) {
if(is_numeric($str_a[$i])) {
$str_a[$i] = $counter++;
}
}
return $str_a;
}
print(change($str_a))
Output:
1)Apple 2)Ball 3)Cat 4)Dog 5)Egg
You can use preg_split and then concatenate it incrementing by 1. This will work also for numbers consisting of multiple digits:
$str_a = "51)Apple 675)Ball 334)Cat 84)Dog 904)Egg";
$a = preg_split('/\b\d+/', $str_a);
$str_b = '';
for($i=0,$c = count($a);$i<$c;$i++){
if($i){
$str_b .= $i.$a[$i];
}
}
echo $str_b;
Output:
1)Apple 2)Ball 3)Cat 4)Dog 5)Egg

PHP Image counter number formatting

I'm building a counter that counts and displays on a web page the number of images in a certain directory.
The code I'm currently using is this:
<?
$d = opendir("images/myimagefolder");
$count = 0;
$min_digits = 7;
while(($f = readdir($d)) !== false)
if(ereg('.jpg$', $f))
++$count;
closedir($d);
if ($min_digits)
{
$count = sprintf('%0'.$min_digits.'f', $count);
}
$number = $count;
$formattedNumber = sprintf("%07d", $number);
$formattedNumber = str_split($formattedNumber, 3);
$formattedNumber = implode(",", $formattedNumber);
print "$formattedNumber";
?>
This works well and outputs a number like the following: 000,000,5
What I am wanting is to have the separating commas occur every 3 digits from the right not the left, so it would appear as 0,000,005
How would this this be done?
I have tried a number of modifications to my sprintf and str_split code but nothing has worked so far. Any help would be greatly appreciated!
<?php
//image count
$images=count(glob("images/myimagefolder/*.jpg"));
//padding
$images=sprintf("%07s",$images);
//commas
$images=strrev(implode(",",str_split(strrev($images),3)));
//outputs 0,000,005
echo $images;
?>
Had a bit of fun coming up with the shortest possible way to accomplish your solution. :)
$formattedNumber = sprintf("%07d", $number);
$formattedNumber = str_split(strrev($formattedNumber), 3);
for (i=0;i<count($formattedNumber); i++)
$formattedNumber[i] = strrev($formattedNumber[i]);
$formattedNumber = implode(",", array_reverse($formattedNumber));
Drop the last four lines. All you need is 'print number_format ($count);'
http://php.net/manual/en/function.number-format.php
Edit, the above won't work with the leading 0's
I found this in the comments on the php site. A little regex magic should do it in one line.
print preg_replace("/(?<=\d)(?=(\d{3})+(?!\d))/",",",$count);
Here's my take with arrays:
$num = sprintf("%07d", 5);
$digits = str_split($num, 1);
$digits = array_reverse($digits);
$chunks = array_map('array_reverse', array_reverse(array_chunk($digits, 3)));
$concat_chunks = array();
foreach ($chunks as $chunk) {
$concat_chunks[] = join('', $chunk);
}
$output = join(',', $concat_chunks);
print $output;

number increment with customized style

I've tried to do a number(decimal) increment which looks like 001 002 003...123,124 in a loop and couldn't find a simple solution.What I've thought now is to check out whether the number is long enough ,if not prefix it some "0".But it seems not good.Any better ideas?
Thanks.
$x = 6
$y = sprintf("%03d",$x);
http://php.net/manual/en/function.sprintf.php
for($i=1;$i<1000;$i++){
$number = sprintf("%03d",$i);
echo "$number <br />";
}
Two options come immediately to mind. First, try str_pad(). It does exactly what you seem to describe.
Second, you could use sprintf() as another has suggested.
If you are not sure how long the various numbers will turn out to be (e.g., they are determined dynamically and no way of knowing what they will be until afterwards), you can use the following code:
<?php
$numbers = array();
for ($i = 0; $i < 2000; $i++)
{
$numbers[] = $i;
}
array_walk($numbers, function(&$item, $key, $len) { $item = sprintf('%0'.$len.'d', $item); }, strlen(max($numbers)));
print_r($numbers);
?>

Categories