I have an array called 'words' storing many words.
For example:
I have 'systematic', 'سلام','gear','synthesis','mysterious', etc.
NB: we have utf8 words too.
How to query efficiently to see which words include letters 's','m','e' (all of them) ?
The output would be:
systematic,mysterious
I have no idea how to do such a thing in PHP. It should be efficient because our server would suffer otherwise.e.
Use a regular expression to split each string into an array of characters, and use array_intersect() to find out if all the characters in your search array is present in the split array:
header('Content-Type: text/plain; charset=utf8');
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$search = array('s','m','e');
foreach ($words as $word) {
$char_array = utf8_str_split($word);
$contains = array_intersect($search, $char_array) == $search;
echo sprintf('%s : %s', $word, (($contains) ? 'True' : 'False'). PHP_EOL);
}
function utf8_str_split($str) {
return preg_split('/(?!^)(?=.)/u', $str);
}
Output:
systematic : True
سلام : False
gear : False
synthesis : False
mysterious : True
Demo.
UPDATE: Or, alternatively, you could use array_filter() with preg_match():
$array = array_filter($words, function($item) {
return preg_match('~(?=[^s]*s)(?=[^m]*m)(?=[^e]*e)~u', $item);
});
Output:
Array
(
[0] => systematic
[4] => mysterious
)
Demo.
This worked to me:
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$letters=array('s','m', 'e');
foreach ($words as $w) {
//print "lets check word $w<br>";
$n=0;
foreach ($letters as $l) {
if (strpos($w, $l)!==false) $n++;
}
if ($n>=3) print "$w<br>";
}
It returns
systematic
mysterious
Explanation
It uses nested foreach: one for the words and the other one for the letters to be matched.
In case any letter is matched, the counter is incremented.
Once the letters loop is over, it checks how many matches were there and prints the word in case it is 3.
Something like this:
$words = array('systematic', 'سلام','gear','synthesis','mysterious');
$result=array();
foreach($words as $word){
if(strpos($word, 's') !== false &&
strpos($word, 'm') !== false &&
strpos($word, 'e') !== false){
$result[] = $word;
}
}
echo implode(',',$result); // will output 'systematic,mysterious'
Your question is wide a little bit.
What I understand from your question that's those words are saved in a database table, so you may filter the words before getting them into the array, using SQL like function.
in case you want to search for a letters in an array of words, you could loop over the array using foreach and each array value should be passed to strpos function.
http://www.php.net/function.strpos
why not use PREG_GREP
$your_array = preg_grep("/[sme]/", $array);
print_r($your_array);
WORKING DEMO
Related
I've spent my last 4 hours figuring out how to ... I got to ask for your help now.
I'm trying to extract from a text multiple substring match my starting_words_array and ending_words_array.
$str = "Do you see that ? Indeed, I can see that, as well as this." ;
$starting_words_array = array('do','I');
$ending_words_array = array('?',',');
expected output : array ([0] => 'Do you see that ?' [1] => 'I can see that,')
I manage to write a first function that can find the first substring matching one of both arrays items. But i'm not able to find how to loop it in order to get all the substring matching my requirement.
function SearchString($str, $starting_words_array, $ending_words_array ) {
forEach($starting_words_array as $test) {
$pos = strpos($str, $test);
if ($pos===false) continue;
$found = [];
forEach($ending_words_array as $test2) {
$posStart = $pos+strlen($test);
$pos2 = strpos($str, $test2, $posStart);
$found[] = ($pos2!==false) ? $pos2 : INF;
}
$min = min($found);
if ($min !== INF)
return substr($str,$pos,$min-$pos) .$str[$min];
}
return '';
}
Do you guys have any idea about how to achieve such thing ?
I use preg_match for my solution. However, the start and end strings must be escaped with preg_quote. Without that, the solution will be wrong.
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr[] = $match[0];
}
}
return $resArr;
}
The result is what the questioner expects.
If the expressions can occur more than once, preg_match_all must also be used. The regex must be modify.
function searchString($str, $starting_words_array, $ending_words_array ) {
$resArr = [];
forEach($starting_words_array as $i => $start) {
$end = $ending_words_array[$i] ?? "";
$regEx = '~'.preg_quote($start,"~").".*?".preg_quote($end,"~").'~iu';
if(preg_match_all($regEx,$str,$match)){
$resArr = array_merge($resArr,$match[0]);
}
}
return $resArr;
}
The resut for the second variant:
array (
0 => "Do you see that ?",
1 => "Indeed,",
2 => "I can see that,",
)
I would definitely use regex and preg_match_all(). I won't give you a full working code example here but I will outline the necessary steps.
First, build a regex from your start-end-pairs like that:
$parts = array_map(
function($start, $end) {
return $start . '.+' . $end;
},
$starting_words_array,
$ending_words_array
);
$regex = '/' . join('|', $parts) . '/i';
The /i part means case insensitive search. Some characters like the ? have a special purpose in regex, so you need to extend above function in order to escape it properly.
You can test your final regex here
Then use preg_match_all() to extract your substrings:
preg_match_all($regex, $str, $matches); // $matches is passed by reference, no need to declare it first
print_r($matches);
The exact structure of your $matches array will be slightly different from what you asked for but you will be able to extract your desired data from it
Benni answer is best way to go - but let just point out the problem in your code if you want to fix those:
strpos is not case sensitive and find also part of words so you need to changes your $starting_words_array = array('do','I'); to $starting_words_array = array('Do','I ');
When finding a substring you use return which exit the function so you want find any other substring. In order to fix that you can define $res = []; at the beginning of the function and replace return substr($str,$pos,... with $res[] = substr($str,$pos,... and at the end return the $res var.
You can see example in 3v4l - in that example you get the output you wanted
I am doing text analysis. I have a table having positive words.The records are being fetched one by one and imploded in an array through mysqli_fetch_array.
while(($rowx = mysqli_fetch_array($resultx,MYSQLI_NUM)))
{
$wordx = implode("", $rowx);
if(strpos($text, $wordx) !== FALSE)
{
$count1 = substr_count($text, $wordx);
$pos_prob += .2 * $count1;
echo "pos prob is".$pos_prob;
}
}
But strpos is not able to match the string that is being fetched from the table.i.e. if text is "It's an excellent book" the if condition is never true. Even though the word excellent is present in the table. And if I hard code the value $wordx as
$wordx='excellent';
Only then it works. Does anyone has any idea why this is happening? :( Any help would be much appreciated :)
I don't understand the need to implode each row. My assumption is that each row has one word.
Simple strpos text matching example:
<?php
$words = array(
'big',
'fat',
'mamma'
);
$text = 'One day fat foo walked to the bar';
$matches = array();
foreach($words as $word) {
if(strpos($text, $word) !== false)
$matches[] = $word;
}
var_dump($matches);
Output:
array (size=1)
0 => string 'fat' (length=3)
Note that this would also match word parts and be case sensitive, so not ideal. For example: 'fat' is contained in the words: 'father', 'infatuated' and 'marrowfat'.
I want to find the position of multiple words in a string.
Forexample :
$str="Learning php is fun!";
I want to get the posion of php and fun .
And my expected output would be :-
1) The word Php was found on 9th position
2) The word fun was found on 16th position.
Here is the code that I tried, but it doesn't work for multiple words.
<?Php
$arr_words=array("fun","php");
$str="Learning php is fun!";
$x=strpos($str,$arr_words);
echo The word $words[1] was found on $x[1] position";
echo The word $words[2] was found on $x[2] position";
Does someone know what's wrong with it and how to fix it?
Any help is greatly appriciated.
Thanks!
To supplement the other answers, you can also use regular expressions:
$str="Learning php is fun!";
if (preg_match_all('/php|fun/', $str, $matches, PREG_OFFSET_CAPTURE)) {
foreach ($matches[0] as $match) {
echo "The word {$match[0]} found on {$match[1]} position\n";
}
}
See also: preg_match_all
Since you can't load an array of string words inside strpos, you could just invoke strpos twice, one for fun and one for php:
$arr_words = array("fun","php");
$str = "Learning php is fun!";
$x[1] = strpos($str,$arr_words[0]);
$x[2] = strpos($str,$arr_words[1]);
echo "The word $arr_words[0] was found on $x[1] position <br/>";
echo "The word $arr_words[1] was found on $x[2] position";
Sample Output
Or loop the word array:
$arr_words = array("fun","php");
$str = "Learning php is fun!";
foreach ($arr_words as $word) {
if(($pos = strpos($str, $word)) !== false) {
echo "The word {$word} was found on {$pos} position <br/>";
}
}
Sample Output
$str="Learning php is fun!";
$data[]= explode(" ",$str);
print_r($data);//that will show you index
foreach($data as $key => $value){
if($value==="fun") echo $key;
if($value==="php") echo $key;
}
Key is the exact position but index start with 0 so keep in mind to modify your code accordingly, may be echo $key+1 (a number of ways, depends on you).
You were doing it in a wrong way check the function
strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
haystack
The string to search in.
needle
If needle is not a string, it is converted to an integer and applied as the ordinal value of a character.
offset
If specified, search will start this number of characters counted from the beginning of the string.
Refer Docs
Here within your example
$arr_words=array("fun","php");
$str="Learning php is fun!";
$x=strpos($str,$arr_words);
$arr_words is an array not a string or not an integer
so you need to loop it or need to manually pass the key as
$x[1] = strpos($str,$arr_words[0]);
$x[2] = strpos($str,$arr_words[1]);
or
foreach($arr_words as $key => $value){
$position = strpos($str,$value);
echo "The word {$value} was found on {$position}th position"
}
Just another answer:
<?php
$arr_words=array("fun","php");
$str="Learning php is fun!";
foreach($arr_words as $needle) {
$x = strpos($str, $needle);
if($x)
echo "The word '$needle' was found on {$x}th position.<br />";
}
?>
You can not use function strpos if the second params is an array.
This is easiest way:
<?php
$words = array("php","fun");
$str = "Learning php is fun!";
foreach ($words as $word) {
$pos = strpos($str, $word);
// Found this word in that string
if($pos) {
// Show you message here
}
}
is there a way to check if two arrays have value that is alike, note not equal but alike. something similar to what mysql has with LIKE to find words that is similar.
in topten.txt i have the following word:
WORKFORCE
in company.txt i have the following url:
Workforce-Holdings-Ltd
So basically i would like to search for the word WORKFORCE in company.txt and the results output should be Workforce-Holdings-Ltd.
Is it possible to do it.
i was maybe thinking preg_grep() perhaps?
Preg_grep is perfect for this. As long as you are searching array values you can just do something like the following:
<?php
$companies = [
'acme inc',
'wORkForce-holdings-ltd'
];
$search = 'WORKFORCE';
var_dump(preg_grep('/' . preg_quote($search, '/') . '/i', $companies));
Here's an ideone example.
You need not use preg match. Instead you can use strpos like:
$result=array();
$a=array('WORKFORCE');
$b=array('Workforce-Holdings-Ltd');
foreach($a as $array1){
foreach($b as $array2){
if (strpos(strtolower($array2),strtolower($array1)) !== false) {
$result[] = 'true';
}
else {
$result[] = 'false';
}
}
}
This will give you an array with true if match is ok or false is match is not ok for all array elements
I'm trying to search for the occurrence of certain words in a string and match them with a short list in an array. I'll explain my question by means of an example.
$arrTitle = explode(" ", "Suburban Apartments");
foreach( $arrTitle as $key => $value){
echo "Name: $key, Age: $value <br />";
$words = array("hotel", "apart", "hostel");
if (in_array($value, $words)) {
echo "Exists";
}
}
I wish to compare a part of the string, in the above example 'Apartments' against the $words array for the occurrence of the string 'Apart'ments.
I hope this makes sense. Is this possible at all?
Thanks
Then you'll have to change a bit your code. Look at this below:
$arrTitle = explode(" ", "Suburban Apartments");
foreach( $arrTitle as $key => $value){
echo "Name: $key, Age: $value <br />";
$words = array("hotel", "apart", "hostel");
foreach($words as $word){
if (stripos($value, $word) !== false) {
echo "Exists";
}
}
}
Note the added foreach on the words to search and the in_array replacement for strpos.
For your personnal information, in_array checks if the $word is in the array as a whole value, which is not what you wanted. You need to check for the existence of each word using strpos or stripos (case insensitive)...
Use regular expressions to match the text.
http://php.net/manual/en/function.preg-match.php
You'll need to cycle through each of your sought array values one at a time so you'll have to loop inside your loop and run the regexp on each one looking for a match.
Make sure to make them case insensitive.