Using OR operator to match the string in php - php

I am getting past of speech in result. I kept condition to feed noun and adjectives on one array like this:
function printTag($tags) {
$var = array();
foreach($tags as $t) {
echo $t['token'] . "/" . $t['tag'] . " ";
if($t['tag'] == 'NN'|| $t['tag']== 'JJ'){
array_push($var, $t['token']) ;
}
}
return $var;
}
but it does not give correct result:
My out put for echo is this :
The/DT quick/JJ brown/JJ fox/NN
jumped/VBD over/IN the/DT lazy/JJ
dog./NN this/DT is/VBZ really/RB yummy/JJ and/CC excellent/JJ
pizza/NN
I/NN have/VBP seen/VBN have/VBP really/RB in/IN love/NN it/PRP
it/PRP
when I do var_dump($var), it gives:
array(6) {
[0]=>
string(5) "quick"
[1]=>
string(5) "brown"
[2]=>
string(4) "dog."
[3]=>
string(5) "yummy"
[4]=>
string(1) "I"
[5]=>
string(4) "love"
}
why some noun and adjectives skipped?

The reason is that the string you are comparing might have endline or whitespace characters in it.
This can be resolved by using the following:
trim($t['tag']) == 'NN'
This is generally a good idea when comparing strings.

Related

Why is the last element in this array being converted to a reference? (PHP)

I am attempting to trim each string in an array of strings with the code below. However, after executing this function, the last element in the array becomes a reference (note the '&' symbol preceding element #3 in the var_dump). Why does this happen? is it a bug or a PEBKAC?
$x = [" ABC ", "DEF ", " GHI", "JKL "];
// Trim all
foreach ($radio_types as &$r)
{
$r = trim($r);
}
var_dump($x);
// Outputs this:
// array(4) { [0]=> string(3) "ABC" [1]=> string(3) "DEF" [2]=> string(3) "GHI" [3]=> &string(3) "JKL" }

PHP - How to switch / reverse values in one column of 2D array

I have an exploded array and I am trying to reverse the first name and last name in a specific column.
Here is the array:
array(729) {
["ID;Position;Name;ER;FF;GA"]=>
array(24) {
[0]=>
string(3) "ID"
[1]=>
string(3) "Position"
[2]=>
string(4) "Name"
[3]=>
string(4) "ER"
[4]=>
string(6) "FF"
[5]=>
string(13) "GA"
}
["7702;Manager;Johnson, Bill;44.5;6T;406"]=>
array(24) {
[0]=>
string(4) "7702"
[1]=>
string(1) "Manager"
[2]=>
string(11) "Johnson, Bill"
[3]=>
string(3) "44.5"
[4]=>
string(4) "6T"
[5]=>
string(1) "406"
}
As you can see, I am need to flip the first name and last name in every 3rd element (index[2]). I was thinking to explode every 3rd element via ',' delimiter (since it is always fname, lname) and then use array_reverse to reverse them... and then reconstruct.
$dump_array = explode(PHP_EOL, $dump);
foreach($dump_array as $line){
$temp[$line]=explode(';', $line);
}
foreach($temp as $ele){
var_dump($temp[$ele]);
$temp[$ele]=array_reverse($temp[$ele[2]]); #I need to do another explode (',') somewhere?
}
You want to do implode instead of explode() in the last line or a sample demo code below :
foreach($dump as $line) {
$temp_str = $line[2];
$temp_str = explode(",", $temp_str);
$line[2] = $temp_str[1] . ", " . $temp_str[0];
}
How does it work: For every array, it picks that array out as $line and then explode the string stored in $line[2] and reverse their order and replace $line[2] with the new reversed value joined with a comma in middle of them
Here is the another way:
$temp = array("asjd", "first , last", "asdjlakd");
foreach($temp as $ele){
if (strpos($ele, ",")!== false){
$data = explode(",", $ele);#I need to do another explode (',') somewhere?
$reverse_data=array_reverse($data);
print_r($reverse_data);
}
}

BcMath Subtracting big numbers + creating a while loop for the difference

I got a question how to round numbers of BCMath? And somehow this code doesn't work properly - cause when I remove the text it becomes xxx.00000 . I need really help on this one I got no idea how should it look like to make it working properly.
Code
if (isset($_POST['licz'])) {
$liczba_a='1111111111111111111';
$liczba_b='1111111111111111100';
echo $a = round(bcsub($liczba_a, $liczba_b)).'<br>';
$diffcap = round($a);
//secure 1
$i = 0;
$count = round($diffcap);
$array= array();
while ($i < $count) {
echo 'array '.$b = bcadd($liczba_a, $i).'<br>';
array_push($array, $b);
++$i;
}
var_dump($array);
} else {
echo "Wpisz liczby.";
}
?>
My output
11 - this is the diff number
array 1111111111111111111
array 1111111111111111112
array 1111111111111111113
array 1111111111111111114
array 1111111111111111115
array 1111111111111111116
array 1111111111111111117
array 1111111111111111118
array 1111111111111111119
array 1111111111111111120
array 1111111111111111121
array(11) { [0]=> string(23) "1111111111111111111
" [1]=> string(23) "1111111111111111112
" [2]=> string(23) "1111111111111111113
" [3]=> string(23) "1111111111111111114
" [4]=> string(23) "1111111111111111115
" [5]=> string(23) "1111111111111111116
" [6]=> string(23) "1111111111111111117
" [7]=> string(23) "1111111111111111118
" [8]=> string(23) "1111111111111111119
" [9]=> string(23) "1111111111111111120
" [10]=> string(23) "1111111111111111121
" }
Assign operator has lower precedence than concatination.
echo 'array '.$b = bcadd($liczba_a, $i).'<br>';
^ it would be first operation.
^ it would be second opration.
You should add parentheses
echo 'array '.($b = bcadd($liczba_a, $i)).'<br>';
But better to avoid double purpose operations.
$b = bcadd($liczba_a, $i);
echo 'array '. $b .'<br>';

Regex to match certain pattern of number combinations

I'm looking making a regex in php that gets data from the following format:
"1,2,3;7,1,3;1" returns an $matches array with "(1,2,3,7,1,3,1)"
"1" returns an $matches with "(1)"
"1;1;3;5;7;10;999" returns an $matches array with "(1,1,3,5,7,10,999)"
"1,1,1;2,5;3,4" doesn't pass since numbers are repeating within semicolon boundaries
"2,3,4;5,;" doesn't pass since it doesn't satisfy the format.
(Quotes in the examples are there to make them easier to read; they should not appear in the real results.)
The format is digit numbers separated by either commas or semicolons and within semicolons they don't repeat each other. It should not accept any other format.
I tried /(^(\d{1,3})$)|(([0-9]+)([,|;]{1}[0-9]+)+)/ but it didn't work.
I also tried /[0-9]+([,|;]{1}[0-9]+)+/ but it didn't worked either. When I got the $matches array it didn't have the values I needed as depicted above.
I'm doing this in PHP 5.2.
Thanks.
This particular problem has too much logic for regular expressions to be practical; this is how you could solve it with regular code:
// reduction function - keeps merging comma separated arguments
// until there's a duplicate or invalid item
function join_unique(&$result, $item)
{
if ($result === false) {
return false;
}
$items = explode(',', $item);
$numbers = array_filter($items, 'is_numeric');
if (count($items) != count($numbers)) {
return false;
}
$unique = array_unique($numbers);
if (count($unique) != count($numbers)) {
return false;
}
return array_merge($result, $numbers);
}
// main function - parse a string of comma / semi-colon separated values
function parse_nrs($str)
{
return array_reduce(explode(';', $str), 'join_unique', array());
}
var_dump(parse_nrs('1,2,3;7,1,3;1'));
var_dump(parse_nrs('1'));
var_dump(parse_nrs('1;1;3;5;7;10;999'));
var_dump(parse_nrs('1,1,1;2,5;3,4'));
var_dump(parse_nrs('2,3,4;5,;'));
Output:
array(7) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "3"
[3]=>
string(1) "7"
[4]=>
string(1) "1"
[5]=>
string(1) "3"
[6]=>
string(1) "1"
}
array(1) {
[0]=>
string(1) "1"
}
array(7) {
[0]=>
string(1) "1"
[1]=>
string(1) "1"
[2]=>
string(1) "3"
[3]=>
string(1) "5"
[4]=>
string(1) "7"
[5]=>
string(2) "10"
[6]=>
string(3) "999"
}
bool(false)
bool(false)
See also: array_reduce() array_unique()
It is impossible to do this in a single step. First you will need to check for the requirement of numbers repeating within a semicolon boundary, and then if it passes that checks split the string.
For example:
if (!preg_match('/\b(\d+),[^;]*\b\1\b/', $string)) {
$matches = preg_split('/[,;]/', $string);
} else {
$matches = NULL;
}
Ideone: http://ideone.com/Y8xf1N

PHP regex. How to get an array of matches?

I have a string in a format like this:
5;1-x;1-2;(1-x;)+
I used 1-x as a notation for all integers from 1 to infinity and (1-x;)+ to mark that the last integer may be repeated any number of times.
Some example strings:
5;1;1;1
5;7;2;7;5;1;9
How can I match these strings with regex and get all the (1-x;)+ matches?
I have tried the following:
preg_match_all('%5;([1-9]{1}[0-9]*);([1-2]);([1-9]{1}[0-9]*;?)+%',
$str, $matches);
And the result for string "5;1;1;1" is:
array(4) {
[0]=>
array(1) {
[0]=>
string(7) "5;1;1;1"
}
[1]=>
array(1) {
[0]=>
string(1) "1"
}
[2]=>
array(1) {
[0]=>
string(1) "1"
}
[3]=>
array(1) {
[0]=>
string(1) "1"
}
}
For the string "5;7;2;7;5;1;9" it is:
array(4) {
[0]=>
array(1) {
[0]=>
string(13) "5;7;2;7;5;1;9"
}
[1]=>
array(1) {
[0]=>
string(1) "7"
}
[2]=>
array(1) {
[0]=>
string(1) "2"
}
[3]=>
array(1) {
[0]=>
string(1) "9"
}
}
As you can see, only the last integer from (1-x;)+ is in the matches array, but I want the matches array to contain values 7, 5, 1, and 9, not just the last one. Is this even possible using regex or do I need to use another approach to validate and get values from these strings?
One way
//$str = "5;1;1;1";
$str = "5;7;2;7;5;1;9";
$pattern = '%^5;([1-9]\d*;)[12];((?:[1-9]\d*;?)+)$%';
$str = preg_replace( $pattern, '$1$2', $str, -1, $count );
if ( $count ) {
print_r( explode( ';', $str ) );
} else {
echo 'Invalid string';
}
The -1 means no limit to the number of replacements.
$count is the number of replacements made. It will be 1 if the string is valid, or 0 otherwise.
The above assumes a string is still valid if it ends in a ;.
I honestly would just explode the string and remove the unwanted first and third elements that like this:
$array = explode(';', $string);
$diff_array = array(0 => 'not_used', 2 => 'not_used');
$final_array = array_key_diff($array, $diff_array);
This gives you an array of all the values except the first and third elements which are the ones which you seem to not be interested in.
If you then need to verify that the remaining elements are indeed integers with value >= 1 you could run an array_filter on it like this:
$filtered_array = array_filter($final_array, function($value) {
if ((string)(int)$value == $value && (int)$value >= 1) return true;
return false;
}

Categories