search for words with sql greater than 3 - php

I using explode in php to split up words, I need then to search for that word in my category list, if a match, then use that category id and create the listing. Only problem is I come across words only one letter ie: "E Cigarettes & Vape Mods"
I don't want to use the "E" that would come up with way too many categories, what is the best solution, if size of word 3 or 4 search that? just thinking aloud. Thanks inadvance

You can use len function: https://www.w3schools.com/sql/sql_func_len.asp
I.e:
select len('word'), outputs 4.

I used strlen then if greater than 3 search that word
$categoryName = str_replace(",","",$categoryName);
$wordsplit = explode(' ',$categoryName);
foreach($wordsplit as $wordCat)
{
if($found) break;
if(strlen($wordCat) > 3)
//DO SOMETHING
}

Related

Using a string as a table to swap alphabet letters

I am trying to take each characters in a sentence and change them to a different one to "encode" the sentence (More like just make it unreadable).
The idea is to take this string : "abc" and turn each characters in it into the next one in the alphabet, giving "bcd". So on an 'A' becomes a 'B' and a 'Z' becomes an 'A' when you reach the end. I created this code which indeed works, but only if you're trying to turn a 'B' into an 'A' which is going backwards in the alphabet.
Here is the code that works (turns B's into A's) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
Which results in this when I run it :
gdkkn rsybjnudqeknv, sghr hr lx ehqrs ptdrshnm. sgymjr enq gdkohmf!
But when I try this second block that turns A's into B's (which is what I want) :
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<26;$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
}
}
}
echo $SentenceToEncode;
?>
I get this :
aaaaa aaaaaaaaaaaaa, aaaa aa aa aaaaa aaaaaaaa. aaaaaa aaa aaaaaaa!
Where did I go wrong? The only difference being the modified alphabet's first and last two letters.
Thanks in advance!
You have to add a break; in your if statement (I would do it for both scripts to save some iterations)! Like this:
if($SentenceToEncode[$i]===$Alphabet[$j]) {
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
Why?
Because if you don't do this it runs the inner loop 26 times for every character! So what that means is:
It first searches the letter h in the normal alphabet and it will find it at position 7. So now it's going to replace the first letter with the letter in the modified alphabet at position 7 which is i. BUT now you don't break the inner loop and it's going for the next iteration to search the first letter, which is now i in the normal alphabet and i is exactly the next letter in the inner loop.
So you replace every character to the end of the modified alphabet! (This didn't happened to you in the first time, because you moved it backwards so it couldn't find it again)
You can do it much easier using str_replace function.
$decoded = array("a", "b", "c", ...., "z");
$encoded = array("z", "a", "b", ...., "y");
$encoded_text = str_replace($decoded, $encoded, $original_text);
$decoded_text = str_replace($encoded, $decoded, $encoded_text);
You can also create initial arrays from strings using str_split function
Try this. You need to execute the second loop as soon it matches the alphabet.
<?php
$SentenceToEncode="hello stackoverflow, this is my first question. thanks for helping!";
$Alphabet="abcdefghijklmnopqrstuvwxyz";
//$ModifiedAlphabet="zabcdefghijklmnopqrstuvwxy";
$ModifiedAlphabet="bcdefghijklmnopqrstuvwxyza";
$SentenceLength=strlen($SentenceToEncode);
for($i=0;$i<$SentenceLength;$i++){
for($j=0;$j<strlen($ModifiedAlphabet);$j++){
if($SentenceToEncode[$i]===$Alphabet[$j]){
$SentenceToEncode[$i]=$ModifiedAlphabet[$j];
break;
}
}
}
echo $SentenceToEncode;
?>

PHP flexible(?) search on CSV file

struggling here with doing a search on an array, for example:
string1; string2; string3;
string4; string5; string6;
If I use preg_match, I can search the array and it will return a result if the search pattern is exactly the same as an item in the array e.g. if the search term is “string1”.
My question is, is there a way to return a positive result if the search string doesn’t have an exact match, e.g. if the search term is “my string” it would return all 6 as suggested results.
Thanks!
You can explode this by ;, loop and use similar_text() function to check how similar is keyword with each string and decide if you want it or not.
$percent = 0;
similar_text($keyword, $string, $percent);
if ($percent > 85) {
// match
}

PHP how to split text that have same delimiter in the text?

I am having trouble to separate the text.
This is the scenario:
$check = "Apple|Orange|Animal|Dog|Grape";
Suppose by using explode i could separate the word with "|", but because the value i retrieved "Animal|Dog" should be a word so in this case, what would be the solution?? I could not use
limit as well because the position or number of text could be different.
The only way to distinctly separate the text is the Animal keyword. Is there any function in php that similar to mysql LIKE syntax?
If Case 2
$check = "Apple|Orange|Animal:Dog|Cat|Grape";
OR
$check = "Apple|Orange|Animal:Fish|Bird|Grape";
where the name of animal could be vary.
Output
"Apple|Orange|Animal:Dog,Cat|Grape" or "Apple|Orange|Animal:Fish,Bird|Grape"
Thanks.
If all you want to do is replace "Animal|" with "Animal:" then you can do a simple str_replace:
$check = "Apple|Orange|Animal|Dog|Grape";
$newCheck = str_replace("Animal|","Animal:"); // will be set to 'Apple|Orange|Animal:Dog|Grape'
Is that what you meant?
EDIT, FOR CASE 2:
I assume you have a string like "Apple|Orange|Animal:Dog|Cat|Grape", which has the category followed by 2 members of the category. From what you've said, you want to transform this string into "Apple|Orange|Animal:Dog,Cat|Grape" with a comma separating the two group members instead of a pipe. This is more complicated than the first case - the category name could vary, and you can't do a simple str_replace starting with the colon because the first member of the group could vary as well. For this case, you'll need to use a regular expression to match and replace the pattern of the string. Here's the code:
$check = "Apple|Orange|Animal:Dog|Cat|Grape";
$newCheck = preg_replace("#(Animal:\w+)\|#", "$1,", $check); // will be set to "Apple|Orange|Animal:Dog,Cat|Grape"
DEMO
Let me explain what this does, in case you're not familiar with regular expressions. The first argument of the preg_replace function, "#(Animal:\w+)\|#", tells PHP to look for all substrings of $check that begin with the text "Animal" followed by a colon, then a string of words with one or more character, and end with a pipe. This will look for the category name as well as the first member of that category in your string. The second argument, ":$1,", tells PHP to change the first pipe after this pattern into a comma. If you have a different category name, simply change the pattern you pass as the first argument to the preg_replace function:
$check = "Apple|Orange|Animal1:Fish|Bird|Grape";
$newCheck = preg_replace("#(Animal1:\w+)\|#", "$1,", $check); // will be set to "Apple|Orange|Animal1:Fish,Bird|Grape"
Let me know if this is hard to follow!
The way I would handle this would be to use a / instead of a | between categories and items. Or use a different delimiter if you really want to keep the | in between categories & items.
$check = "Apple|Orange|Animal/Dog|Grape";
$ex=explode("|", $check);
but if you don't want to do that... then if you know what your category names are like "animal", you could explode the array on | and assume that if your current value is "animal", then the next element in the array is going to be "dog", "cat", whatever. This is not a good solution though, and would not work for multiple category levels.
You have spaces between Apple and orange, like this Apple | Orange. But there is no space between Animal and Dog Like this Animal|Dog. If this is the situation, you can explode it like this
$check = "Apple | Orange | Animal|Dog | Grape";
$ex=explode(" | ", $check);
Which will return array in format
array("Apple","Orange","Animal|Dog","Grape");
You can manipulate above array again to get Animal
I hope this is what you meant
Edit : A rough solution could be :
<?
$check = "Apple|Orange|Animal|Dog|Grape";
$ex=explode("|",$check);
if(in_array("Animal",$ex))
{
echo "Animal:";
}
if(in_array("Dog",$ex)){
echo "Dog";
}
?>
So in this case the position of Animal and Dog doesnot matter
str_replace("Animal|","Animal:",$check);
then do explode

Compare words, also need to look for plurals and ing?

I have two list of words, suppose LIST1 and LIST2. I want to compare LIST1 against LIST2 to find the duplicates, but it should find the plural of the word as well as ing form also. For example.
Suppose LIST1 has word "account", and LIST2 has words "accounts,accounting" When i do compare the result should show two match for word "account".
I am doing it in PHP and have the LIST in mysql tables.
You can use a technique called porter stemming to map each list entry to its stem, then compare the stems. An implementation of the Porter Stemming algorithm in PHP can be found here or here.
What I would do is take your word and compare it directly to LIST2 and at the same time remove your word from every word your're comparing looking for a left over ing, s, es to denote a plural or ing word (this should be accurate enough). If not you'll have to generate an algorithm for making plurals out of words as it not as simple as adding an S.
Duplicate Ending List
s
es
ing
LIST1
Gas
Test
LIST2
Gases
Tests
Testing
Now compare List1 to List2. During the same loop of comparison do a direct comparision to items and one where the word, from list 1, is removed from the current word you're looking at in list 2. Now just check is this result is in the Duplicate Ending List.
Hope that makes sense.
The problem with that is, in English at least, plurals are not all standard extensions, nor are present participles. You can make an approximation by using all words +'ing' and +'s', but that will give false positives and negatives.
You can handle it directly in MySQL if you wish.
SELECT DISTINCT l2.word
FROM LIST1 l1, LIST l2
WHERE l1.word = l2.word OR l1.word + 's' = l2.word OR l1.word + 'ing' = l2.word;
This function will output the plural of a word.
http://www.exorithm.com/algorithm/view/pluralize
Something similar could be written for gerunds and present participles (ing forms)
You might consider using the Doctrine Inflector class in conjunction with a stemmer for this.
Here's the algorithm at a high level
Split search string on spaces, process words individually
Lowercase the search word
Strip special characters
Singularize, replace differing portion with wildcard ('%')
Stem, replace differing portion with wildcard ('%')
Here's the function I put together
/**
* Use inflection and stemming to produce a good search string to match subtle
* differences in a MySQL table.
*
* #string $sInputString The string you want to base the search on
* #string $sSearchTable The table you want to search in
* #string $sSearchField The field you want to search
*/
function getMySqlSearchQuery($sInputString, $sSearchTable, $sSearchField)
{
$aInput = explode(' ', strtolower($sInputString));
$aSearch = [];
foreach($aInput as $sInput) {
$sInput = str_replace("'", '', $sInput);
//--------------------
// Inflect
//--------------------
$sInflected = Inflector::singularize($sInput);
// Otherwise replace the part of the inflected string where it differs from the input string
// with a % (wildcard) for the MySQL query
$iPosition = strspn($sInput ^ $sInflected, "\0");
if($iPosition !== null && $iPosition < strlen($sInput)) {
$sInput = substr($sInflected, 0, $iPosition) . '%';
} else {
$sInput = $sInput;
}
//--------------------
// Stem
//--------------------
$sStemmed = stem_english($sInput);
// Otherwise replace the part of the inflected string where it differs from the input string
// with a % (wildcard) for the MySQL query
$iPosition = strspn($sInput ^ $sStemmed, "\0");
if($iPosition !== null && $iPosition < strlen($sInput)) {
$aSearch[] = substr($sStemmed, 0, $iPosition) . '%';
} else {
$aSearch[] = $sInput;
}
}
$sSearch = implode(' ', $aSearch);
return "SELECT * FROM $sSearchTable WHERE LOWER($sSearchField) LIKE '$sSearch';";
}
Which I ran with several test strings
Input String: Mary's Hamburgers
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'mary% hamburger%';
Input String: Office Supplies
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'offic% suppl%';
Input String: Accounting department
SearchString: SELECT * FROM LIST2 WHERE LOWER(some_field) LIKE 'account% depart%';
Probably not perfect, but it's a good start anyway! Where it will fall down is when multiple matches are returned. There's no logic to determine the best match. That's where things like MySQL fulltext and Lucene come in. Thinking about it a little more, you might be able to use levenshtein to rank multiple results with this approach!

PHP Bolding The 'x' Instance of a Variable In a String

Basically I have a variable which contains a few paragraphs of text and I have a variable which I want to make bold within the paragraphs. (By wrapping <strong></strong> tags around it). The problem is I don't want to make all instances of the word bold, or else I'd just do a str_replace(), I want to be able to wrap the first, second, fourth, whatever instance of this text in the tags, at my own discretion.
I've looked on Google for quite awhile but it's hard to find any results related to this, probably because of my wording..
I guess that preg_replace() could do the trick for you. The following example should skip 2 instances of the word "foo" and highlight the third one:
preg_replace(
'/((?:.*?foo.*?){2})(foo)/',
'\1<strong>\2</strong>',
'The foo foo fox jumps over the foo dog.'
);
(Sorry, I forgot two questionmarks to disable the greediness on my first post. I edited them in now.)
You can probably reference 'Replacing the nth instance of a regex match in Javascript' and modify it to work for your needs.
Since you said you wanted to be able to define which instances should be highlighted and it sounds like that will be arbitrary, something like this should do the trick:
// Define which instances of a word you want highlighted
$wordCountsToHighlight = array(1, 2, 4, 6);
// Split up the paragraph into an array of words
$wordsInParagraph = explode(' ', $paragraph);
// Initialize our count
$wordCount = 0;
// Find out the maximum count (because we can stop our loop after we find this one)
$maxCount = max($wordCountsToHighlight);
// Here's the word we're looking for
$wordToFind = 'example'
// Go through each word
foreach ($wordsInParagraph as $key => $word) {
if ($word == $wordToFind) {
// If we find the word, up our count.
$wordCount++;
// If this count is one of the ones we want replaced, do it
if (in_array($wordCount, $wordCountsToHighlight)) {
$wordsInParagragh[$key] = '<strong>example</strong>';
}
// If this is equal to the maximum number of replacements, we are done
if ($wordCount == $maxCount) {
break;
}
}
}
// Put our paragraph back together
$newParagraph = implode(' ', $wordsInParagraph);
It's not pretty and probably isn't the quickest solution, but it'll work.

Categories