I'm trying to stop users searching with terms that give far too many results.
For example, I'd like users to be able to search for "Big Island" but not search for "Island".
I tried this:
$array = array("island", "islands", "island's", "islet", "ilsets", "reef", "reefs", "shoal", "shoals");
if (0 < count(array_intersect(array_map('strtolower', explode(' ', $searchTerm)), $array)))
{
echo "No results. The search term used was too general.";
exit();
}
But that stops the search for any phrase with the stop words in it.
I guess I'm looking for something that goes like:
if the string contains this word or that word (and only one of those words!) stop what you're doing, else carry on...
look at the strstr function it may help you http://php.net/manual/en/function.strstr.php
Maybe look at searching after removing "stop words" which are words like "the" "and" etc. So remove the "stop words", then check if the search string is empty. Also make sure to add your other words to the stop words list.
Try looking at in_array()
That way you can just say
if (in_array($searchterm,$array))
{
// stop searching
}
Maybe let the user search and then present an "Related searches" à la Google...
Why don't you try with regular expressions - here is a simple demo. You can of course generate the character groups (big|small) etc. from predefined arrays
$regex = '/^(big|small)\s+(Island|islet|reef)$/';
if ( 1 === preg_match($regex, 'big reef ') {...}
Related
I have searched and searched but I cannot find anything quite exactly like what I need. I have a code:
$repeater = "pompom";
if (preg_match('/([a-zA-Z])\1{3}/', $repeater)) {
echo "Yes, $repeater does repeat 3 characters.<br>";
}
else {
echo "No, $repeater does not repeat 3 characters.<br>";
}
(I can barely understand regex as it is... so just ignore my current regex.. it's just a mixture of randomness I began to type.)
Anyhow, I need the regex code to return
true for words like
pompom
grugru
mopmop
cancan
etc...
and return false for words like
coocoo
daadaa
allall
giigii
etc.
The regex must detect and return true for any word that has 3 different characters that repeat more than once in that word.
This must work for words that have characters that are not necessarily in sequence with one another. I have found solutions to that. Words such as "cooo" or "pooool" is not what I need to apply this regex for. Note: This must return True only for words that have 3 or more different letters in the word and are repeated more than once. Such as, pompom..
This should return false for words like coocoo because there are only 2 different letters in the word.
Again, please ignore my current regex it was just what I had when I decided to ask for some help. I've tried probably 200 different methods, all wrong of course :].
Any help would be nice, maybe we can figure this out together I just need some ideas to bounce off of.
The following regex will perform as requested:
^((.)(?!\2)(.)(?!\2)(?!\3).)\1$
https://regex101.com/r/eHKzWB/3
I've a part of an xml that i'm importing that is not in a regular order. It could be for example:
87||1|#88||2|#89||2|50198#41||1|#3||1|117#20|||#6|20|1|#24|||78#145|5||#36|||90#37|||96#29|||67#26|||#27|||#25|||
I create a function like this:
function caratteristiche1($title) {
$title=substr($title,11,1);
return $title;
}
to receive the value of #88 but sometimes #88 is not in that position, and other times #88 is not present.
I would like to use a function that will search for #88 and give as result the value present after the 2 subseguent pipes.
What can i do?
Thank you so much!
If the distance between the #88 and the two pipes is identical in all cases, you can use a Regular Expression with a "positive lookbehind assertion", see http://php.net/manual/en/regexp.reference.assertions.php
If not, you probably need to use plain PHP to locate the #88, then take the remaining substring from there on and search for the two pipes.
EDIT after your answer of "NO":
In this case, I wouldn't do it with RegEx.
Try something like that (might not be 100% accurate syntax):
$pos88 = strpos('#88', $string);
newStr = substr($string, $pos88);
$posPipes = strpos('||', $newStr);
// ... and so forth ...
I'm currently looking to implement a search function on my website.
I have it working with 1 word/name, but I can't seem to figure out how to split and identify certain parts of the search string.
Example:
I have a user in my database with the name "Steve de Vette"
(My country has words in between almost all of the first and last names but not always, and sometimes more than one. ex: "Kees van der Berg") But his name is of course split up in multiple parts. "vNaam", "Tvoegsel"(meaning the "de" or "van der") and "aNaam".
This complicates things a bit for me, since I now have to split the search string, which on it's own isn't a big deal. But I need to know how I can get the correct results every time.
So I guess it comes down to this: How can I make it so that the name is split up like it should, or maybe there's a way to strip these thing all together, but for the likes of me I can't seem to figure it out.
Any help would be greatly appreciated!
EDIT:
I have tried just exploding the name and searching with multiple OR_LIKE clauses. This works until I have no "tussenvoegsel" and one of the Like statements reads "OR anaam LIKE '%%'"
split the string with explode and search for the first and last item.
$string1 = "Steve de Vette";
$string2 = "Kees van der Berg";
$ex1 = explode(" ", $string2);
$nr = count($ex1);
echo $ex1[0]; //firstname
echo ' ';
echo $ex1[$nr-1]; //lastname
Well you can use the PHP string searching funciton.
$pos = strpos($string, $character);
You could use this to find the first space in the name. So if you take "Steve de Vette", you could first find Steve as the first name, then the rest of the string you could search again or keep the rest of it as the last name.
This is a snippet of code taken from my own site.
$fname = strstr($entry," ",true); <-- finds the first name (all characters up to the first space)
$len = strlen($fname) + 1; <-- skips over the space to the last name
$entrylen = strlen($entry); <-- gets the length of the search string used
$sname = substr($entry, $len, $entrylen); <-- gets the rest of the string (last name)
Hope you find this helpful
What i do is strip out any spaces all together. I store spaces in my database like normal but use the replace feature when searching to strip out spaces. then strip out spaces from the search field as well and use the like with the wild card on the right hand side. I try to make the search as simple as possible. searching with one word seems to work better all together so forcing one word seems to be the thing that works for me.
I am looking to develop a search function that allows users to just search for the item, or modify their search with a price range in brackets. So that is to say if they are looking for a car, then they can enter either car and receive all cars in the database or they can enter car (100, 299) or car(100, 299) and receive only cars in the database with the price range of 100 to 299.
Before what I did was three different explode function calls, but that was cumbersome and looked ridiculously ugly. I also tried to put the the brackets in an array and then compare that against the word searched (a word is basically an array of characters) but that didn't work. Finally I have been reading up on strpos and substr but they don't seem to fit the requirements as strpos returns the first occurrence of the the character and substr returns the characters within a specified length after a specific occurrence.
So for example the problem with strpos is the user can just enter ( and no ) bracket and I'll make a call to my search function with who knows what. And for example the problem with substr is that the price range can vary wildly.
You can use preg_match to parse the search string - I'm assuming that's the part you're having issues with.
if (preg_match('/car ?\(([^,]+), ?([^\)]+)\)/', $search_text, $matches)) {
$low_price = $matches[1];
$high_price = $matches[2];
//do your price filtering here
}
The regular expression may need a little tweaking, I don't remember offhand if parentheses need to be escaped in character classes.
Yes, Sam is right. You should do this with regular expressions.
Look for preg_match() on the documentation
To complete his answer, the regular expression for your case is:
$regex = "^([a-zA-Z]+)\s\(([0-9]+),([0-9]+)\)$"
if (preg_match($regex, $search_text, $matches)) {
$type = $matches[0];
$low_price = $matches[1];
$high_price = $matches[2];
//do your price filtering here
}
Be careful, as the array containing matches starts at index 0, not one.
I am using cakephp 1.3 and I have textarea where users submit articles. On submit, I want to look into the article for certain key words and and add respective tags to the article.
I was thinking of preg_match, But preg_match pattern has to be string. So I would have to loop through an array(big).
Is there a easier way to plug in the keywords array for the pattern.
I appreciate all your help.
Thanks.
I suggest treating your array of keywords like a hash table. Lowercase the article text, explode by spaces, then loop through each word of the exploded array. If the word exists in your hash table, push it to a new array while keeping track of the number of times it's been seen.
I ran a quick benchmark comparing regex to hash tables in this scenario. To run it with regex 1000 times, it took 17 seconds. To run it with a hash table 1000 times, it took 0.4 seconds. It should be an O(n+m) process.
$keywords = array("computer", "dog", "sandwich");
$article = "This is a test using your computer when your dog is being a dog";
$arr = explode(" ", strtolower($article));
$tracker = array();
foreach($arr as $word){
if(in_array($word, $keywords)){
if(isset($tracker[$word]))
$tracker[$word]++;
else
$tracker[$word] = 1;
}
}
The $tracker array would output: "computer" => 1, "dog" => 2. You can then do the process to decide what tags to use. Or if you don't care about the number of times the keyword appears, you can skip the tracker part and add the tags as the keywords appear.
EDIT: The keyword array may need to be an inverted index array to ensure the fastest lookup. I am not sure how in_array() works, but if it searches, then this isn't as fast as it should be. An inverted index array would look like
array("computer" => 1, "dog" => 1, "sandwich" => 1); // "1" can be any value
Then you would do isset($keywords[$word]) to check if the word matches a keyword, instead of in_array(), which should give you O(1). Someone else may be able to clarify this for me though.
If you don't need the power of regular expressions, you should just use strpos().
You will still need to loop through the array of words, but strpos is much, much faster than preg_match.
Of course, you could try matching all the keywords using one single regexp, like /word1|word2|word3/, but I'm not sure it is what you are looking for. And also I think it would be quite heavy and resource-consuming.
Instead, you can try with a different approach, such as splitting the text into words and checking if the words are interesting or not. I would make use of str_word_count() using someting like:
$text = 'this is my string containing some words, some of the words in this string are duplicated, some others are not.';
$words_freq = array_count_values(str_word_count($text, 1));
that splits the text into words and counts occurrences. Then you can check with in_array($keyword, $words_freq) or array_intersect(array_keys($words_freq), $my_keywords).
If you are not interested, as I guess, to the keywords case, you can strtolower() the whole text before proceeding with words splitting.
Of course, the only way to determine which approach is the best is to setup some testing, by running various search functions against some "representative" and quite long text and measuring the execution time and resource usage (try microtime(TRUE) and memory_get_peak_usage() to benchmark this).
EDIT: I cleaned up a bit the code and added a missing semi-colon :)
If you want to look for multiple words from an array, then combine said array into an regular expression:
$regex_array = implode("|", array_map("preg_escape", $array));
preg_match_all("/($regex_array)/", $src, $tags);
This converts your array into /(word|word|word|word|word|...)/. The arrray_map and preg_escape part is optional, only needed if the $array might contain special characters.
Avoid strpos and loops for this case. preg_match is faster for searching after alternatives.
strtr()
If given two arguments, the second
should be an array in the form
array('from' => 'to', ...). The return
value is a string where all the
occurrences of the array keys have
been replaced by the corresponding
values. The longest keys will be tried
first. Once a substring has been
replaced, its new value will not be
searched again.
Add tags manually? Just like we add tags here at SO.