PHP count instances of array items in a string - php

In PHP 7.3:
Given this array of low relevancy keywords...
$low_relevancy_keys = array('guitar','bass');
and these possible strings...
$keywords_db = "red white"; // desired result 0
$keywords_db = "red bass"; // desired result 1
$keywords_db = "red guitar"; // desired result 1
$keywords_db = "bass guitar"; // desired result 2
I need to know the number of matches as described above. A tedious way is to convert the string to a new array ($keywords_db_array), loop through $keywords_db_array, and then loop through $low_relevancy_keys while incrementing a count of matches. Is there a more direct method in PHP?

The way you described in your question but using array_* functions:
echo count(array_intersect(explode(' ', $keywords_db), $low_relevancy_keys));
(note that you can replace explode with preg_split if you need to be more flexible)
or using preg_match_all (that returns the number of matches):
$pattern = '~\b' . implode('\b|\b', $low_relevancy_keys) . '\b~';
echo preg_match_all($pattern, $keywords_db);
demo

Related

Find numbers on a string and order by them

I have this string
$s = "red2 blue5 black4 green1 gold3";
I need to order by the number, but can show the numbers.
Numbers will always appears at the end of the word.
the result should be like:
$s = "green red gold black blue";
Thanks!
Does it always follow this pattern - separated by spaces?
I would break down the problem as such:
I would first start with parsing the string into an array where the key is the number and the value is the word. You can achieve this with a combination of preg_match_all and array_combine
Then you could use ksort in order to sort by the keys we set with the previous step.
Finally, if you wish to return your result as a string, you could implode the resulting array, separating by spaces again.
An example solution could then be:
<?php
$x = "red2 blue5 black4 green1 gold3";
function sortNumberedWords(string $input) {
preg_match_all('/([a-zA-Z]+)([0-9]+)/', $input, $splitResults);
$combined = array_combine($splitResults[2], $splitResults[1]);
ksort($combined);
return implode(' ', $combined);
}
echo sortNumberedStrings($x);
The regex I'm using here matches two seperate groups (indicated by the brackets):
The first group is any length of a string of characters a-z (or capitalised). Its worth noting this only works on the latin alphabet; it won't match ö, for example.
The second group matches any length of a string of numbers that appears directly after that string of characters.
The results of these matches are stored in $splitResults, which will be an array of 3 elements:
[0] A combined list of all the matches.
[1] A list of all the matches of group 1.
[2] A list of all the matches of group 2.
We use array_combine to then combine these into a single associative array. We wish for group 2 to act as the 'key' and group 1 to act as the 'value'.
Finally, we sort by the key, and then implode it back into a string.
$s = "red2 blue5 black4 green1 gold3";
$a=[];
preg_replace_callback('/[a-z0-9]+/',function($m) use (&$a){
$a[(int)ltrim($m[0],'a..z')] = rtrim($m[0],'0..9');
},$s);
ksort($a);
print " Version A: ".implode(' ',$a);
$a=[];
foreach(explode(' ',$s) as $m){
$a[(int)ltrim($m,'a..z')] = rtrim($m,'0..9');
}
ksort($a);
print " Version B: ".implode(' ',$a);
preg_match_all("/([a-z0-9]+)/",$s,$m);
foreach($m[1] as $i){
$a[(int)substr($i,-1,1)] = rtrim($i,'0..9');
}
ksort($a);
print " Version C: ".implode(' ',$a);
Use one of them, but also try to understand whats going on here.

How can i replace all specific strings in a long text which have dynamic number in between?

I am trying to replace strings contains specific string including a dynamic number in between.
I tried preg_match_all but it give me NULL value
Here is what i am actually looking for with all details:
In my long text there are values which contains this [_wc_acof_(some dynamic number)] , i.e: [_wc_acof_6] i want to convert them to $postmeta['_wc_acof_14'][0]
This can be multiple in the same long text.
I want to run through with this logic:
1- First i get all numbers after [_wc_acof_ and save them in array by using preg_match_all as guided here get number after string php regex
2- Then i run a foreach loop and set my arrays for patterns and replacements with that number i.e:
foreach ($allMatchNumbers as $MatchNumber){
$key = "[_wc_acof_" . $MatchNumber. "]";
$patterns[] = $key;
$replacements[] = $postmeta[$key][0];
}
3- Then i do replace with this echo preg_replace($patterns, $replacements, $string);
But i am unable to get preg_match_all it gives me NULL where i tried below
preg_match_all('/[_wc_acof_/',$string,$allMatchNumbers );
Please Help? i am not sure if preg_grep is better than this?
It seems you want to process the input in stages, to obtain all the numbers in specific lexical context first, and then modify the user input using some lookup technique.
The first step can be implemented as
preg_match_all('~\[_wc_acof_(\d+)]~', $text, $matches)
that extracts all sequences of one or more digit in between [_wc_acof_ and ] into Group 1 (you can access the values via $matches[1]).
Then, you may fill the $replacements array using these values.
Next, you can use
preg_replace_callback('~\[_wc_acof_(\d+)]~', function($m) use ($replacements){
return $replacements[$m[1]];
}, $text)
See the PHP demo:
<?php
$text = '<p>[_wc_acof_6] i want to convert this and it contains also this [_wc_acof_9] or can be this [_wc_acof_11] number can never be static</p>';
if (preg_match_all('~\[_wc_acof_(\d+)]~', $text, $matches)) {
foreach($matches[1] as $matched){
$replacements[$matched] = 'NEW_VALUE_FOR_'.$matched.'_KEY';
}
print_r($replacements);
echo preg_replace_callback('~\[_wc_acof_(\d+)]~', function($m) use ($replacements){
return $replacements[$m[1]];
}, $text);
}
Output:
Array
(
[0] => 6
[1] => 9
[2] => 11
)
NEW_VALUE_FOR_6_KEY i want to convert this and it contains also this NEW_VALUE_FOR_9_KEY or can be this NEW_VALUE_FOR_11_KEY number can never be static

print random string from string with multiply words

I am new to php and trying out some different things.
I got a problem with printing a random value from a string from multiply values.
$list = "the weather is beautiful tonight".
$random = one random value from $list, for example "beautiful" or "is"
Is there any simple way to get this done?
Thanks!
well, as #Dagon suggested, you can use explode() to get an array of strings, then you can use rand($min, $max) to get an integer between 0 and the length of your array - 1. and then read the string value inside your array at the randomly generated number position.
// First, split the string on spaces to get individual words
$arg = explode(' ',"the weather is beautiful tonight");
// Shuffle the order of the words
shuffle($arg);
// Display the first word of the shuffled array
print $arg[0];

Stop explode after certain index [duplicate]

This question already has answers here:
How to limit the elements created by explode()
(4 answers)
Closed 1 year ago.
How can I stop explode function after certain index.
For example
<?php
$test="The novel Prognosis Negative by Art Vandelay expresses protest against many different things. The story covers a great deal of time and takes the reader through many different places and events, as the author uses several different techniques to really make the reader think. By using a certain type of narrative structure, Vandelay is able to grab the reader’s attention and make the piece much more effective and meaningful, showing how everything happened";
$result=explode(" ",$test);
print_r($result);
?>
What if want to use only first 10 elements ($result[10])
How can I stop explode function once 10 elements are filled.
One way is to first trim the string upto first 10 spaces (" ")
Is there any other way, I don't want to store the remaining elements after limit anywhere (as done using positive limit parameter)?
What's about that third parameter of the function?
array explode ( string $delimiter , string $string [, int $limit ] )
check out the $limit parameter.
Manual: http://php.net/manual/en/function.explode.php
An example from the manual:
<?php
$str = 'one|two|three|four';
// positive limit
print_r(explode('|', $str, 2));
// negative limit (since PHP 5.1)
print_r(explode('|', $str, -1));
?>
The above example will output:
Array (
[0] => one
[1] => two|three|four ) Array (
[0] => one
[1] => two
[2] => three )
In your case:
print_r(explode(" " , $test , 10));
According to the php manual , when you're using the limit parameter:
If limit is set and positive, the returned array will contain a
maximum of limit elements with the last element containing the rest of
string.
Therefore , you need to get rid of the last element in the array.
You can do it easily with array_pop (http://php.net/manual/en/function.array-pop.php).
$result = explode(" " , $test , 10);
array_pop($result);
You could read the documentation for explode:
$result = explode(" ", $test, 10);

PHP : Get a number between 2 strings

I have this string:
a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}
I want to get number between "a:" and ":{" that is "3".
I try to user substr and strpos but no success.
I'm newbie in regex , write this :
preg_match('/a:(.+?):{/', $v);
But its return me 1.
Thanks for any tips.
preg_match returns the number of matches, in your case 1 match.
To get the matches themselves, use the third parameter:
$matches = array();
preg_match(/'a:(\d+?):{/', $v, $matches);
That said, I think the string looks like a serialized array which you could deserialize with unserialize and then use count on the actual array (i.e. $a = count(unserialize($v));). Be careful with userprovided serialized strings though …
If you know that a: is always at the beginning of the string, the easiest way is:
$array = explode( ':', $string, 3 );
$number = $array[1];
You can use sscanfDocs to obtain the number from the string:
# Input:
$str = 'a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}';
# Code:
sscanf($str, 'a:%d:', $number);
# Output:
echo $number; # 3
This is often more simple than using preg_match when you'd like to obtain a specific value from a string that follows a pattern.
preg_match() returns the number of times it finds a match, that's why. you need to add a third param. $matches in which it will store the matches.
You were not too far away with strpos() and substr()
$pos_start = strpos($str,'a:')+2;
$pos_end = strpos($str,':{')-2;
$result = substr($str,$pos_start,$pos_end);
preg_match only checks for appearance, it doesn't return any string.

Categories