PHP - Array size returns 1? - php

Under Return Values for Count()
Returns the number of elements in var. If var is not an array or an object with implemented Countable interface, 1 will be returned. There is one exception, if var is NULL, 0 will be returned.
I have a string which is filled with letters and numbers and I'm using preg_match_all() to extract those numbers. As I recall preg_match_all fills the contents of the array given in the 3rd parameter with the results. Why does it return 1?
What am I doing wrong in my code?
$string = "9hsfgh563452";
preg_match_all("/[0-9]/",$string,$matches);
echo "Array size: " . count($matches)."</br>"; //Returns 1
echo "Array size: " . sizeof($matches)."</br>"; //Returns 1
print_r($matches);
I would like to sum the contents of the array (which is all the numbers returned in the string) array_sum() didn't work ; it is a string array and I don't know how to convert it to an int array because I'm not using any delimiters like ' , ' and such. Is there a more efficient way in doing this?
Help appreciated.

The count is 1 because $matches is an array which contains another array inside. Specifically, $matches[0] is an array that contains each match of the zero-th capturing group (the whole regular expression).
That is, $matches looks like this:
Array
(
[0] => Array // The key "0" means that matches for the whole regex follow
(
[0] => 9 // and here are all the single-character matches
[1] => 5
[2] => 6
[3] => 3
[4] => 4
[5] => 5
[6] => 2
)
)

The result of preg_match_all is actually an array of an array:
Array
(
[0] => Array
(
[0] => 9
[1] => 5
[2] => 6
[3] => 3
[4] => 4
[5] => 5
[6] => 2
)
)
So you'll need to do something like:
echo "Array size: " . count($matches[0]);
echo "Array sum: " . array_sum($matches[0]);

This is due to the way preg_match_all returns results. Its main array elements are the preg brackets (expression matches), whilst the contents of them are what you matched.
In your case, you have no sub-expressions. The array will therefore only have one element - and that element will contain all your digits.
To sum them up, simply do this:
$sum = 0;
$j = count($matches[0]);
for ($i = 0; i < $j; ++$i) {
$sum += (int)$matches[0][$i];
}

Try using $matches[0] instead of $matches (returns 7).
Then if you want to sum all the numbers you can use the foreach function

Related

PHP extract (parsing) string

I'm using a regex to check a string for a certain format.
preg_match('/^\/answer ([1-9][0-9]*) (.{1,512})$/', $str, $hit, PREG_OFFSET_CAPTURE);
Using this regex, the posted string needs to have this format:
/answer n x
n -> an integer > 0
x -> a string, 512 chars maximum
Now how to extract "n" and "x" the easiest way using PHP?
For example:
/answer 56 this is my sample text
Should lead to:
$value1 = 56;
$value2 = "this is my sample text";
Running this simple piece of code
<?php
$hit = [];
$str = '/answer 56 this is my sample text';
preg_match('/^\/answer ([1-9][0-9]*) (.{1,512})$/', $str, $hit, PREG_OFFSET_CAPTURE);
echo'<pre>',print_r($hit),'</pre>';
Will show you, that $hit has following values:
<pre>Array
(
[0] => Array
(
[0] => /answer 56 this is my sample text
[1] => 0
)
[1] => Array
(
[0] => 56
[1] => 8
)
[2] => Array
(
[0] => this is my sample text
[1] => 11
)
)
1</pre>
Here:
$hit[0][0] is full string that matches your pattern
$hit[1][0] is a substring that matches pattern [1-9][0-9]*
$hit[2][0] is a substring that matches pattern .{1,512}
So,
$value1 = $hit[1][0];
$value2 = $hit[2][0];

Wrong result array_map function

this is my input array...
$var = Array ( [0] => 57;5;7;Hertha BSC - SV Werder Bremen [1] => Heim )
I change it to another array with this function
$int_array = array_map("intval", explode(";", $var[0]));
When I call this array I get this result
Array ( [0] => 57 [1] => 5 [2] => 7 [3] => 0 )
But why is Array position [3] = 0. There must be "Hertha BSC..."?
The description of the intval function, according to the PHP docs is:
Get the integer value of a variable
The integer value of Hertha BSC - SV Werder Bremen (the 4th element of the array created by exploding ; on "57;5;7;Hertha BSC - SV Werder Bremen") is not clear.
Throwing a string at it will not yield meaningful results in this context. So, I don't think it's the wrong result.
Here's something that might get you a little closer to what I think you're after, though
$var = [
'57;5;7;Hertha BSC - SV Werder Bremen',
'Heim'
];
$int_array = array_map(
function($item) {
// In cases where the exploded array item is not entirely made up of digits, return it as a string.
if (0 === preg_match('/\d+/', $item)) {
return $item;
}
// else, cast to int.
return intval($item);
},
explode(";", $var[0])
);

Why do dollar symbols not appear in a double-quoted PHP string?

I am running some simple code from http://www.writephponline.com/
Inputs
$str = "$Q$14";
$arr = explode("$", $str);
print_r($arr);
Outputs
Array ( [0] => [1] => 14 )
My question is why array at index 0 is empty, shouldn't that be letter Q?
Please check the photo
The main problem is the choice of the double quoted string type:
$Q = '$Q';
print_r(explode('$', "$Q$14"));
Array ( [0] => [1] => Q [2] => 14 )
So what is happening in your code is a "double quoted" string replaces valid variable names to the value of them, where $Q is a valid name and $14 is not because they may not start with a digit.
echo "$Q$14";
Notice: Undefined variable: Q in ... on line ...
$14
So you're actually concatenating null . '$14' as variable $Q does not exist in your code and that value is null so the end value is: $14
If you would use a 'literal' string, it works as expected:
echo '$Q$14';
$Q$14
The other thing is that explode() splits the string into 2 pieces from the first delimiter found, so you will have a left and a right part. Any traditional delimiter found only causes 1 index to be appended. The string starts with a delimiter so the first array index is expected to be null because no value exists left of the first character.
print_r(explode('.', 'left.right'));
print_r(explode('.', 'left.middle.right'));
print_r(explode('$', '$Q$14'));
Array ( [0] => left [1] => right )
Array ( [0] => left [1] => middle [2] => right )
Array ( [0] => [1] => Q [2] => 14 )
If you really want to achieve desired output with the same string you specified then try this one, add backslash(\) before first $
$str = "\$Q$14";
$arr = explode("$", $str);
print_r($arr);
I tried it and it worked.

get an array with a predefined structure using preg_match or preg_match_all

Here is an example string:
"60 reviews from 12 people, 20% of users"
(Let's call it $v)
I have been using preg_match_all to get an array with all the numbers
$pattern = '!\d+!';
preg_match_all($pattern, $v, $matches, PREG_SET_ORDER);
The result I get is:
Array
(
[0] => Array
(
[0] => 60
)
[1] => Array
(
[0] => 12
)
[2] => Array
(
[0] => 20
)
)
But despite trying for some time I haven't been able to get what I want. What I want is this:
Array
(
[0] => 60
[1] => 12
[2] => 20
)
Maybe should I be using preg_match instead? but with preg_match I only get one value... Or maybe along with a loop? It looks like an ugly hack... There should be a profesional way out there... Thanks in advance to PHP experts! ;)
Presuming the format always stays the same, you can do the following:
<?php
// Input string/line
$v = "60 reviews from 12 people, 20% of users";
// Match regex (0-9; min 1 or max unlimited numbers)
preg_match_all("/[0-9]{1,}/", $v, $matches);
// Remove/sub key
$matches = $matches[0];
// Echo out
print_r($matches);
?>
This will output:
Array (
[0] => 60 // < Access using $matches[0]
[1] => 12 // < Access using $matches[1]
[2] => 20 // < Access using $matches[2]
)
Is this what you want?, array_values($array)

Conversion from string to int does not work

I use a regex to get a value from a document and store it in a variable called $distance. That is a string, but I have to put it in an int column of a table in a database.
Of course, normally I would go and say
$distance=intval($distance);
But it doesn't work! I really don't know why.
This is all I am doing:
preg_match_all($regex,$content,$match);
$distance=$match[0][1];
$distance=intval($distance);
The regex is correct, if I echo $distance, it is e.g. "0" - but I need it to be 0 instead of "0". Using intval() will somehow always convert it to an empty string.
EDIT 1
The regex is this:
$regex='#<value>(.+?)</value>#'; // Please, I know I shouldn't use regex for parsing XML - but that is not the problem right now
Then I proceed with
preg_match_all($regex,$content,$match);
$distance=$match[0][1];
$distance=intval($distance);
If you'd do print_r($match) you'd see that the array you need is $match[1]:
$content = '<value>1</value>, <value>12</value>';
$regex='#<value>(.+?)</value>#';
preg_match_all($regex,$content,$match);
print_r($match);
Output:
Array
(
[0] => Array
(
[0] => <value>1</value>
[1] => <value>12</value>
)
[1] => Array
(
[0] => 1
[1] => 12
)
)
In this case:
$distance = (int) $match[1][1];
var_dump($distance);
Output: int(12)
Alternatively, you can use PREG_SET_ORDER flag, i.e. preg_match_all($regex,$content,$match,$flags=PREG_SET_ORDER);, $match array has this structure:
Array
(
[0] => Array
(
[0] => <value>1</value>
[1] => 1
)
[1] => Array
(
[0] => <value>12</value>
[1] => 12
)
)
There must be a space, or possibly (been there, done that) an 0xA0 byte before the zero. Use "\d" in your regexp to be sure to get digits.
Edit: you can clean up the value with
$value = (int)trim($value, " \t\r\n\x0B\xA0\x00");
http://php.net/manual/en/function.trim.php
Why do you need the question mark in your regex? Try this:
$regex='#<value>(.+)</value>#';

Categories