Retrieving Values from an Array in PHP - php

If you make an array and fill it with values with the function preg_match_all , how do you retrieve each separate value from the array (basically scan through it from index 0 to length)? I want to take each value and perform another function on it, so how would I return each value stored in the array? (I want arr's value at index 0, at index 1, etc.)
$contents = file_get_contents('words.txt');
$arr = array();
preg_match_all($pattern, $contents, $arr); //finds all matches
$curr = current($arr);
I tried doing this (my pattern was written elsewhere) and echoing it afterwards, but I keep getting the string "Array".

$contents=file_get_contents('words.txt');
$arr=array();
preg_match_all($pattern,$contents,$arr);//finds all matches
foreach ($arr as $item) {
$curr=current($arr);
// do something
}

preg_match_all() takes at least Parameters: (1) The Regex. (2) The String to Match your Regex against. It also takes a third Optional Parameter which gets automatically populated with all the found matches. This 3rd Argument is a Numerically indexed Array. Thus you can loop through it like like you would a Normal Array as well as treat it like any normal Array (which it is). The Snippet below demonstrate this using your Code:
<?php
$contents = file_get_contents('words.txt');
//$arr = array(); //<== NO NEED TO PRE-DECLARE THIS HERE
preg_match_all($pattern, $contents, $arr);//finds all matches
// IF YOU JUST WANT THE 1ST (CURRENT MATCH), SIMPLY USE current:
$curr = current($arr);
// YOU MAY KEEP MOVING THE CURSOR TO THE NEXT ITEM LIKE SO:
$next1 = next($arr);
$next2 = next($arr);
// OR JUST LOOP THROUGH THE FOUND MATCHES: $arr
foreach($arr as $match){
$curr = current($arr); //<== BUT THIS IS SOMEWHAT REDUNDANT WITHIN THIS LOOP.
// THE VARIABLE $match CONTAINS THE MATCHED STRING WITHIN THE CURRENT ITERATION:
var_dump($match); //<== RETURNS THE CURRENT VALUE WITHIN ITERATION
}
// YOU MAY EVEN USE NUMERIC INDEXES TO ACCESS THEM LIKE SO.
$arrLen = count($arr);
$elem0 = isset($arr[0])?$arr[0]:null;
$elem1 = isset($arr[1])?$arr[1]:null;
$elem2 = isset($arr[2])?$arr[2]:null;
$elem3 = isset($arr[3])?$arr[3]:null; //<== AND SO ON...

If I understand well your question, you want to know how looks the results stored in the third parameter of preg_match_all.
preg_match_all stores the results in the third parameter as a 2-dimensional array.
Two structures are possible and can be explicitly set with two constants in the fourth parameter.
Let's say you have a pattern with two capture groups and your subject string contains 3 occurrences of your pattern:
1) PREG_PATTERN_ORDER is the default setting that returns something like that:
[
0 => [ 0 => 'whole match 1',
1 => 'whole match 2',
2 => 'whole match 3' ],
1 => [ 0 => 'capture group 1 from match 1',
1 => 'capture group 1 from match 2',
2 => 'capture group 1 from match 3' ],
2 => [ 0 => 'capture group 2 from match 1',
1 => 'capture group 2 from match 2',
2 => 'capture group 2 from match 3' ]
]
2) PREG_SET_ORDER that returns something like that:
[
0 => [ 0 => 'whole match 1',
1 => 'capture group 1 from match 1',
2 => 'capture group 2 from match 1' ],
1 => [ 0 => 'whole match 2',
1 => 'capture group 1 from match 2',
2 => 'capture group 2 from match 2' ],
2 => [ 0 => 'whole match 3',
1 => 'capture group 1 from match 3',
2 => 'capture group 2 from match 3' ]
]
Concrete examples can be found in the PHP manual. You only need to choose which is the more convenient option for what you need to do.
So, to apply your function, all you need to do is to perform a foreach loop or to use array_map (that is a hidden loop too, but shorter and slower).
In general, if you aren't sure what is the structure of a variable, you can use print_r or var_dump to know how it looks like.

Related

PHP - Check if any nested array is not empty

If i have a nested array as follows, how can I check if any of the dates arrays are NOT empty?
$myArray = [
'1' => [ 'dates' => []],
'2' => [ 'dates' => []],
'3' => [ 'dates' => []],
...
]
I know I can check this by doing a foreach loop:
$datesAreEmpty = true;
foreach($myArray as $item) {
if (!empty($item['dates'])) {
$datesAreEmpty = false;
}
}
Is there a more elegant way to do this?
You need to do in 3 steps
check each element is_array()
if Yes, then check size($element)
if its greater than 0 then true otherwise false
More elegant? No, I don't think so. Actually, you can break the loop after the first non-empty to make this check short-circuit, that's a tiny improvement, but this is THE way to do it.
Using array_walk (which will be mentioned in minutes I'm sure) is slower and less readable; also, there are tricky solutions with serialization (finding non-empty date strings by strpos or regex) but you don't gain anything by applying them.
Stick with this solution, and use a break on first hit. #chefstip ;)
Using second argument for count will count you all items in array including subarrays. This is not a solution for all cases as in other answers, and has some initial assumptions which can be not clear, but still:
// Suppose you have array of your structure
$myArray = [
'1' => ['dates' => []],
'2' => ['dates' => []],
'3' => ['dates' => []],
];
// compare
var_dump(count($myArray), count($myArray, true));
// you see `3` and `6`
// - 3 is count of outer elements
// - 6 is count of all elements
// Now if there're no other keys in subarrays except `dates`
// you can expect that `count` of all elements is __always__
// twice bigger than `count` of outer elements
// When you add some value to `dates`:
$myArray = [
'1' => ['dates' => ['date-1']],
'2' => ['dates' => []],
'3' => ['dates' => []],
];
// compare
var_dump(count($myArray), count($myArray, true));
// you see `3` (outer elements) and `7` (all elements)
// So, you have __not empty__ `dates` when `count` of all elements
// is more than doubled count of outer elements:
$not_empty_dates = 2 * count($myArray) < count($myArray, true);
// Of course if you have other keys in subarrays
// code should be changed accordingly, that's why
// it is not clear solution, but still it can be used
A working fiddle https://3v4l.org/TanG4.
Can be done iteratively with array_filter:
// This will be empty if all array elements are empty.
$filtered = array_filter($myArray, '_filter_empty');
/**
* Recursively remove empty elements from array.
*/
function _filter_empty($element) {
if (!is_array($element)) {
return !empty($element);
}
return array_filter($element, '_filter_empty');
}

PHP - get unique strings from array

I am new to this place and I have a question about PHP that I can't figure out.
What I am trying to do is create an array of strings, but that's not the problem. The problem is I have no idea how to get the only string that I need.
Example code:
$array = [];
$array[$game] = $string;
I want to keep creating strings for one single game but there will but more and more strings coming in the array from different games. I want to get only the ones from a single game, I don't know if you get what I'm talking about but I hope so because I'm frustrated that I can't figure out a way.
You have to create sub array for each game then set strings inside
// checking it sub array already not exits to not overwrite it
if( isset($array[$game]) ){
$array[$game] = array();
}
then only insert your string inside it
$array[$game][] = $string1;
$array[$game][] = $string2;
...
as result you will have
array('somegame' => array(
0 => "some game string 1",
1 => "some game string 2",
...
)
)
Your question is too simple.
You are already appending the strings to array by the key of game id.
$array = [];
$array[$game] = $string;
So, your array will look like:
array(
1 => array('string 1', 'string 2'),
2 => array('string 3', 'string 4'),
3 => array('string 5', 'string 6'),
//..... and more
)
Where keys 1, 2 and 3 are the game ids.
If you want to retrieve the keys in case of game ids 1 and 2:
$game = 1;
$gameStringsOne = $arr[$game];
$game = 2;
$gameStringsTwo = $arr[$game];
Use multi-dimensional array like
$array = [];
$array[$game] = [ $string1, $string2 ];
Read the docs Use a multi-dimentional array, push strings to an array and then assign that to another array, that way you can have multiple strings to a game
<?php
$stringArray = array("str","str2");
// if needed do array_push($stringArray,"str3","str4");
array_push($gamelist['game'], $stringArray);
?>
get an array of strings when acessing game from gamelist
read more

Fetch first item from the value list using (comma) limiter

I have items visually:
array(
0 => '"abc","def",ghi', //"abc","def",ghi is just value. 0----N is the expected array
1 => '"jkl", ...',
);
My actual written code in use is, so this is the concern:
array(
'"abc","def",ghi', //"abc","def",ghi is just value. 0----N is the expected array
'"jkl", ...',
);
I want to fetch "abc", but need to ignore the rest ,"def",ghi
How would I do that with PHP?
Thanks for any pointers.
$firstitem=explode(',',$yourarray[0]);
or
explode(",", $yourarray[0], 2);//to limit the explode so the resulting array does not contain unwanted elements
$firstitem[0] will contain the first characters of the first element from yourarray including "
$exp = explode(',', $myArray[0]);
print $exp[0];
$v = array(
0 => '"abc","def",ghi', //"abc","def",ghi is just value. 0----N is the expected array
1 => '"jkl", ...',
);
$x = reset(explode(',', $v[0]));
this is it?

How to get this element from this array

I have an array $arr that when I var_dump looks like this. What's the easiest way to get the 2nd last item ('simple' in this case). I can't do $arr[4] because the number of items may vary per url, and I always want just the 2nd last. (note that there's an extra empty string at the end, which will always be there.)
array
0 => string 'http:' (length=5)
1 => string '' (length=0)
2 => string 'site.com'
3 => string 'group'
4 => string 'simple'
5 => string 'some-test-url'
6 => string '' (length=0)
So long as it is not a keyed or hashed array and it has more than two items...
$arr[count($arr) - 2];
Note: that my interpretation of second to last is second from the end. This may differ from yours. If so, subtract 3.
Get the count and subtract 3?
$arr[count($arr)-3]
if (!empty($arr) && count($arr)>1){
//or > 2, -3 for your extra ending
$val = $arr[count($arr)-2];
}
Should help you.
$second_last = count($array) - 3;
$value = $array[$second_last];
$arrayLen=count($arr);
echo $arr[$arrayLen-2];
Yet another alternative:
echo current(array_slice($data, -3, 1));

Negotiate arrays inside an array

When i perform a regular expression
preg_match_all('~(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)~', $content, $turls);
print_r($turls);
i got an array inside array. I need a single array only.
How to negotiate the arrays inside another arrays
By default preg_match_all() uses PREG_PATTERN_ORDER flag, which means:
Orders results so that $matches[0] is
an array of full pattern matches,
$matches1 is an array of strings
matched by the first parenthesized
subpattern, and so on.
See http://php.net/preg_match_all
Here is sample output:
array(
0 => array( // Full pattern matches
0 => 'http://www.w3.org/TR/html4/strict.dtd',
1 => ...
),
1 => array( // First parenthesized subpattern.
// In your case it is the same as full pattern, because first
// parenthesized subpattern includes all pattern :-)
0 => 'http://www.w3.org/TR/html4/strict.dtd',
1 => ...
),
2 => array( // Second parenthesized subpattern.
0 => 'www.w3.org',
1 => ...
),
...
)
So, as R. Hill answered, you need $matches[0] to access all matched urls.
And as budinov.com pointed, you should remove outer parentheses to avoid second match duplicate first one, e.g.:
preg_match_all('~https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?~', $content, $turls);
// where $turls[0] is what you need
Not sure what you mean by 'negociate'. If you mean fetch the inner array, that should work:
$urls = preg_match_all('~(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)~', $content, $matches) ? $matches[0] : array();
if ( count($urls) ) {
...
}
Generally you can replace your regexp with one that doesn't contain parenthesis (). This way your results will be hold just in the $turls[0] variable :
preg_match_all('/https?\:\/\/[^\"\'\s]+/i', file_get_contents('http://www.yahoo.com'), $turls);
and then do some code to make urls unique like this:
$result = array_keys(array_flip($turls[0]));

Categories