Mysql search string - php

I have a search box that will search for a keyword in the field : description
then return results. its done in mysql and php.
the description can go from 10 to 600 characters long. I would like to return only a part of result.
for example :
I am searching for the keyword= John
instead of displaying the whole field description as the result I want to see the sentence where the keyword is found only: ... Hello my name is john and I ...
not the whole paragraph.
I can use sql or php whichever one is better. I tried substring but failed implementing it any example would be great.
SELECT SUBSTR(description,2,100)
FROM screenplays
WHERE lower(description) like '% $search_word_fix %'

I thought by query, it will hamper performance. Because of string calculations. So I have done this by php substr function logic.
SELECT description
FROM screenplays
WHERE lower(description) like '% $search_word_fix %'
//$description will have longer string.
//$short_string will have shorter string.
$short_string=get_less_string($description,'john',20);
function get_less_string($string,$key,$num){
$desc=explode($key,$string);
$left='...'.substr($desc[0], strlen($desc[0])-$num,$num);
$right=substr($desc[1],0,$num).'...';
$final_string=$left.$key.$right;
return $final_string;
}

if you want to use php.. I had written a function few months back. It searches for keywords in a text and returns a string with 'bold' keywords. Hope this helps.
$str = 'I have a search box that will search for a keyword in the field : description then return results. its done in mysql and php. the description can go from 10 to 600 characters long. I would like to return only a part of result. for example : I am searching for the keyword= John instead of displaying the whole field description as the result I want to see the sentence where the keyword is found only: ... Hello my name is john and I ... not the whole paragraph.
I can use sql or php whichever one is better. I tried substring but failed implementing it any example would be great.';
$search = array();
$search[] = "example";
echo descriptionSearch($str,$search);
function descriptionSearch($desc,$words,$max_number_words = 30)
{
$descs = explode(" ",$desc);
$positions = array();
$i = 0;
foreach($words as $w)
{
$j = 0;
foreach($descs as $d)
{
$w = strtolower(trim($w));
$d = strtolower(trim($d));
if(strpos($d,$w) !== false)
{
$positions[] = $j;
$descs[$j] = str_replace($w,"<span style='font-weight: bold;'>".$d."</span>",$d);
}
$j++;
}
$i++;
}
$max = 0;
if(sizeof($positions) > 0)
{
foreach($positions as $j)
{
if($max < 4)
{
$i = $j -5;
if($i < 0)
{
$i = 0;
}
while($i < ($j+10))
{
$toreturn .= $descs[$i]." ";
$i++;
}
$toreturn .= " ...";
$max++;
}
}
}
else
{
for($i=0; $i < $max_number_words; $i++)
{
$toreturn .= $descs[$i]." ";
}
}
return $toreturn;
}

You CAN do it either way, and both will be about as efficient. PHP is probably a better more flexible solution, but just for kicks I tried to do it in MySQL, to see how it would work
SELECT SUBSTR(
description,
if(INSTR(description, '$search_word_fix') - 10 < 0,
0,
(INSTR(description, '$search_word_fix') - 10)),
if(
INSTR(description, '$search_word_fix') + 10 >
length(description),
length(description),
NSTR(description, '$search_word_fix') + 10))
FROM screenplays
WHERE lower(description) LIKE '% $search_word_fix %'

Modified answer, This can search better. In this example. I am searching for 'for example' or 'john'
$str = 'I have a search box that will search for a keyword in the field : description then return results. its done in mysql and php. the description can go from 10 to 600 characters long. I would like to return only a part of result. for example : I am searching for the keyword= John instead of displaying the whole field description as the result I want to see the sentence where the keyword is found only: ... Hello my name is john and I ... not the whole paragraph.
I can use sql or php whichever one is better. I tried substring but failed implementing it any example would be great.';
$search = array();
$search[] = "for example";
$search[] = "john";
echo descriptionSearch($str,$search);
function descriptionSearch($desc,$words,$max_number_words = 30)
{
$positions = array();
$i = 0;
foreach($words as $w)
{
$w = strtolower(trim($w));
$d = strtolower(trim($d));
if(strpos($desc,$w) !== false)
{
$positions[] = strpos($desc,$w);
$desc = str_replace($w,"<span style='font-weight: bold;'>".substr($desc,strpos($desc,$w),strlen($w))."</span>",$desc);
}
$i++;
}
$max = 0;
if(sizeof($positions) > 0)
{
foreach($positions as $j)
{
if($max < 4)
{
$i = $j -16;
if($i < 0)
{
$i = 0;
}
$toreturn .= substr($desc,$i,80);
$toreturn .= " ...";
$max++;
}
}
}
else
{
$descs = explode(" ",$desc);
for($i=0; $i < $max_number_words; $i++)
{
$toreturn .= $descs[$i]." ";
}
}
return $toreturn;
}

Related

Php apply function in array if next entry is integer (Concatenate a valid FEN string)

Trying to build a valid FEN string.
Given this 8*8 array example, symbolizing a checker board, ("1" are empty squares):
$checkerboard = [["r","n","b","q","k","b","n","r"],["p","p","p","p","p","p","p","p"],["1","1","1","1","1","1","1","1"],["1","1","1","1","1","1","1","1"],["1","1","1","1","P","1","1","1"],["1","1","1","1","1","1","1","1"],["P","P","P","P","1","P","P","P"],["R","N","B","Q","K","B","N","R"]]
In situ, this is the position:
The valid result I am looking for is:
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR
And by now my output is:
rnbqkbnr/pppppppp/11111111/11111111/1111P111/11111111/PPPP1PPP/RNBQKBNR
Obviously, any integer entry in the array should be sum to the next, only if the next entry is an integer, and if so the next entry should be discarded till the end.
By iterating the array, I am not sure how to apply something like array_walk() or array_map() here in a simple way. Maybe a simple string operation is enough?
$FEN = "";
for ($i = 0;$i < 8;$i++){
for ($j = 0;$j < 8;$j++){
if ($checkerboard[$i][$j] === "1"){
if ($checkerboard[$i][$j + 1] === "1"){
/* How to iterate till the end */
$FEN .= (int)$checkerboard[$i][$j] + (int)$checkerboard[$i][$j+1];
}
} else {
$FEN .= $checkerboard[$i][$j];
}
}
$FEN .= "/";
}
Any insights?
Example online: https://3v4l.org/tuqqo
$checkerboard = [["r","n","b","q","k","b","n","r"],["p","p","p","p","p","p","p","p"],["1","1","1","1","1","1","1","1"],["1","1","1","1","1","1","1","1"],["1","1","1","1","P","1","1","1"],["1","1","1","1","1","1","1","1"],["P","P","P","P","1","P","P","P"],["R","N","B","Q","K","B","N","R"]];
$parts = array();
foreach ($checkerboard as $innerArray) {
$num = null;
$str = '';
foreach($innerArray as $innerval){
if(is_numeric($innerval)){
$num += (int) $innerval;
}
else{
if(!is_null($num)){
$str .=$num;
$num = null;
}
$str .=$innerval;
}
}
if(!is_null($num)){
$str .=$num;
}
array_push($parts,$str);
}
$result = implode('/',$parts);
above code will generate required output and store it on the $result.

Php removing specific special character and php algorithm ideas

so I ended up with this project, that,due to my opinion, is some levels greater than my skills, so I would like you to help me.
This project's functionality is to write some words in those 4 columns,which have to be combined.The words that are in the same column mustn't be combined. You can only combine words with the rest of the columns.
I will give you the full code so you can see what I have done.
The second question I have is how you delete a special character(in this case, the "\n")
<?php
if(isset($_POST['submit']))
{
if(isset($_POST["separator"])){$separator= $_POST["separator"];}
if(isset($_POST["match"])){$matchType = $_POST["match"];$matchArr = array();
foreach($matchType as $match)
{
$matchArr = $match;
}}
$j=0;
$columnCount=array();
$wordArr[] = array();
$wordArrRows[] = array();
$protasi="";
$wordsCombinations = 1;
$wordsCounter = 0;
for($i=0; $i<4; $i++)
{ $words=0;
$enterChar=0;
if(isset($_POST["in$i"]) && !empty($_POST["in$i"]))
{
$input=$_POST["in$i"];
$enterChar = substr_count($input,"\n");
$words= $enterChar+1;
if($words>0)
{
$wordArr[$j]= explode("\n",$input);
$wordArrRows[$j]= $words;
$j++;
}
$wordsCombinations*=$words;
}
}
$i2=0;
$columnCounter = array_fill(0, $j, "0");
while($wordsCounter < $wordsCombinations)
{
if($i2<sizeof($columnCounter) && $columnCounter[$i2] < $wordArrRows[$i2])
{
echo "grammi: ".$i2." <br>";
$i=0;
for($i=0; $i<$j; $i++)
{
//echo "wordArr[".$i."][".$columnCounter[$i]."]".$separator;
echo $wordArr[$i][$columnCounter[$i]]." ";
}
$columnCounter[$i2]++;
if($columnCounter[$i2] >= $wordArrRows[$i2] ){$columnCounter[$i2]=0;}
echo "<br>";
}
$i2++;
if($i2>=sizeof($columnCounter)){$i2=0;}
$wordsCounter++;
}
}
?>
(NOTE: don't use the radio buttons or the check boxes, they're not functional).
EDIT
What is the expected result for that example?
The second question: trim() to delete "\n"

Check if Variable is smaller than others, and which one its smaller than. PHP

I have been working on my scoring system and came accros this.
I have 4 vars.
$newscore
$score1
$score2
$score3
I want to see if new score is lower than the 3 others, and if so which ones. The scoring system requires you to have the lowest possible score.
I have the following code:
if($newscore > $score1){
if($newscore > $score2){
if($newscore < $score3){
//has to be score3 to replace.
}
}else{
...
}
}
But what I'm wondering is if I will have to continue on with all these if statements, or is there something a lot shorter and easier? I need to replace the the score that it is smaller than, but not the one its larger than. Score 1 2 and 3 are all the players stats. And if I do have to continue on with all the if statements, how would the code look (its baffling my logic)?
you should probably use an array
$scores = array(8, 15, 10); //previous scores
$new_score = 5;
$new_score_smallest = true;
foreach($scores as $score) {
if($score < $new_score) {
$new_score_smallest = false;
}
}
if($new_score_smallest) {
echo "Best score!";
}
else {
echo "Not the best score :(";
}
If you only want to remember the 3 best scores:
$scores = array(5, 6, 8);
$new_score = 7;
for($i = 0; $i < count($scores); $i++) {
if($new_score < $scores[$i]) {
$scores[$i] = $new_score;
break;
}
}
You could do something like the following:
EDIT: As you're using a database, you would execute the query similar to this:
SELECT scores FROM scores_table replacing the table name and column name with your corresponding data.
$scores = [$score1, $score2] // add as many as you like
$new_score = $scores[0]; // assign a baseline
foreach ($scores as $score) {
if ($score < $new_score) {
$new_score = $score;
}
}
Hope that helps.
You can use array_search and min
$newscore = 2;
$scores = array($score1, $score2, $score3);
if($newscore < min($scores)){
$scores[array_search(min($scores), $scores)] = $newscore;
}
array $score lowest score will be updated if $newscore is inferior
Put your scores in an array or anything iterable (like a query result, whether you use PDO or mysqli).
Let's say your scores are in $scores array (it will be the same if $score is a PDOStatement for example) and ordered (use ORDER ASC in your query):
$scores = [105, 201, 305];
$newscore = '186';
$hiscore = false;
$beaten = [];
foreach ($score as $k => $score) {
if ($newscore > $score) {
$hiscore = true;
$beaten[] = $score;
unset($scores[$k]);
}
}
if ($hiscore) {
echo 'New high score!'.PHP_EOL;
echo 'Better than '.implode(', ', $beaten).PHP_EOL;
echo 'But not better than '.implode(', ', $scores);
} else {
echo 'Try harder!';
}
<?php
$newscore = 78;
$score1 = 23;
$score2 = 201;
$score3 = 107;
$max = max([$score1, $score2, $score3]);
if ($max < $newscore) {
echo "New best score ! ({$newscore})";
} else {
echo "Not the best score !\nCurrent: {$newscore}\nBest: {$max}";
}

Rewrite a large number of for loops into something shorter

I have the following code:
for($a=1; $a<strlen($string); $a++){
for($b=1; $a+$b<strlen($string); $b++){
for($c=1; $a+$b+$c<strlen($string); $c++){
for($d=1; $a+$b+$c+$d<strlen($string); $d++){
$tempString = substr_replace($string, ".", $a, 0);
$tempString = substr_replace($tempString, ".", $a+$b+1, 0);
$tempString = substr_replace($tempString, ".", $a+$b+$c+2, 0);
$tempString = substr_replace($tempString, ".", $a+$b+$c+$d+3, 0);
echo $tempString."</br>";
}
}
}
}
What it does is to make all possible combinatons of a string with several dots.
Example:
t.est123
te.st123
tes.t123
...
test12.3
Then, I add one more dot:
t.e.st123
t.es.t123
...
test1.2.3
Doing the way I'm doing now, I need to create lots and lots of for loops, each for a determined number of dots. I don't know how I can turn that example into a functon or other easier way of doing this.
Your problem is a combination problem. Note: I'm not a math freak, I only researched this information because of interest.
http://en.wikipedia.org/wiki/Combination#Number_of_k-combinations
Also known as n choose k. The Binomial coefficient is a function which gives you the number of combinations.
A function I found here: Calculate value of n choose k
function choose($n, $k) {
if ($k == 0) {return 1;}
return($n * choose($n - 1, $k - 1)) / $k;
}
// 6 positions between characters (test123), 4 dots
echo choose(6, 4); // 15 combinations
To get all combinations you also have to choose between different algorithms.
Good post: https://stackoverflow.com/a/127856/1948627
UPDATE:
I found a site with an algorithm in different programming languages. (But not PHP)
I've converted it to PHP:
function bitprint($u){
$s= [];
for($n= 0;$u > 0;++$n, $u>>= 1) {
if(($u & 1) > 0) $s[] = $n;
}
return $s;
}
function bitcount($u){
for($n= 0;$u > 0;++$n, $u&= ($u - 1));
return $n;
}
function comb($c, $n){
$s= [];
for($u= 0;$u < 1 << $n;$u++) {
if(bitcount($u) == $c) $s[] = bitprint($u);
}
return $s;
}
echo '<pre>';
print_r(comb(4, 6));
It outputs an array with all combinations (positions between the chars).
The next step is to replace the string with the dots:
$string = 'test123';
$sign = '.';
$combs = comb(4, 6);
// get all combinations (Th3lmuu90)
/*
$combs = [];
for($i=0; $i<strlen($string); $i++){
$combs = array_merge($combs, comb($i, strlen($string)-1));
}
*/
foreach ($combs as $comb) {
$a = $string;
for ($i = count($comb) - 1; $i >= 0; $i--) {
$a = substr_replace($a, $sign, $comb[$i] + 1, 0);
}
echo $a.'<br>';
}
// output:
t.e.s.t.123
t.e.s.t1.23
t.e.st.1.23
t.es.t.1.23
te.s.t.1.23
t.e.s.t12.3
t.e.st.12.3
t.es.t.12.3
te.s.t.12.3
t.e.st1.2.3
t.es.t1.2.3
te.s.t1.2.3
t.est.1.2.3
te.st.1.2.3
tes.t.1.2.3
This is quite an unusual question, but I can't help but try to wrap around what you are tying to do. My guess is that you want to see how many combinations of a string there are with a dot moving between characters, finally coming to rest right before the last character.
My understanding is you want a count and a printout of string similar to what you see here:
t.est
te.st
tes.t
t.es.t
te.s.t
t.e.s.t
count: 6
To facilitate this functionality I came up with a class, this way you could port it to other parts of code and it can handle multiple strings. The caveat here is the strings must be at least two characters and not contain a period. Here is the code for the class:
class DotCombos
{
public $combos;
private function combos($string)
{
$rebuilt = "";
$characters = str_split($string);
foreach($characters as $index => $char) {
if($index == 0 || $index == count($characters)) {
continue;
} else if(isset($characters[$index]) && $characters[$index] == ".") {
break;
} else {
$rebuilt = substr($string, 0, $index) . "." . substr($string, $index);
print("$rebuilt\n");
$this->combos++;
}
}
return $rebuilt;
}
public function allCombos($string)
{
if(strlen($string) < 2) {
return null;
}
$this->combos = 0;
for($i = 0; $i < count(str_split($string)) - 1; $i++) {
$string = $this->combos($string);
}
}
}
To make use of the class you would do this:
$combos = new DotCombos();
$combos->allCombos("test123");
print("Count: $combos->combos");
The output would be:
t.est123
te.st123
tes.t123
test.123
test1.23
test12.3
t.est12.3
te.st12.3
tes.t12.3
test.12.3
test1.2.3
t.est1.2.3
te.st1.2.3
tes.t1.2.3
test.1.2.3
t.est.1.2.3
te.st.1.2.3
tes.t.1.2.3
t.es.t.1.2.3
te.s.t.1.2.3
t.e.s.t.1.2.3
Count: 21
Hope that is what you are looking for (or at least helps)....

Feature like FB's "X, Y and Z other people like this"

I'm trying to implement something like facebook's like widget which says something like:
You, Name1, Name2 and 20 other people like this
I fetched all my data to be able to display this HTML, but I can't seem to find the right algo to form the HTML string.
My main problem is that I don't know when to put the and string or the , (comma) string. If I just had to put names, it would work, but the problem is that the You string always has to be first.
I'm going to paste my code here and the output I'm getting for some special cases (it's PHP).
$current_user = 0;
$html = "";
$count = count($result);
$key = 0;
foreach($result as $liked){
if($key + 1 > $limit)
break;
if($liked->uid == $user->uid){
$current_user = 1;
continue;
}
$html .= "<a href='".$liked->href."'>".$liked->name."</a>";
if($key < $count - 2)
$html .= ", ";
elseif($key == $count - 2 && $key + 1 != $limit)
$html .= " and ";
$key++;
}
if($current_user){
$userHtml = "You";
if($count > 2)
$userHtml .= ", ";
elseif($count > 1)
$userHtml .= " and ";
$html = $userHtml.$html;
}
$html = "♥ by ".$html;
if($count > $limit){
$difference = $count - $limit;
$html .= " and ".$difference." ".format_plural($difference,"other","others");
}
return $html;
And in the special case where the current user is the last one to like this, it will show:
♥ by You, admin, edu2004eu and
Notice the and word doesn't have anything after it, because You should have been after it, but I put it at the beginning. Any help? I just need the logic, not the actual code.
You can try something like this:
$likedBy = array('admin', 'eduard', 'jeremy', 'someoneelse');
// check if I like it and if so move me to the front
if (in_array($currentUsername, $likedBy)) {
$me = array_search($currentUsername, $likedBy);
unset($likedBy[$me]);
array_unshift($likedBy, 'You');
}
// remove anything after the limit
$extra = array_splice($likedBy, 3);
// the comma list
$html = implode(', ', $likedBy);
// any extras? if so, add them here, if not rewrite the list so
// it's "You, Eduard and admin"
if (!empty($extra)) {
$html .= ' and '.count($extra);
} else {
$lastguy = array_splice($likedBy, 1);
$html = implode(', ', $likedBy).' and '.$lastguy;
}
$html .= ' like this';
Eduard,
You can fix this simply by putting $key++; at the top of the loop and taking out all the places where you have $key + 1 in the loop.
I think what's happening is that $key + 1 is assuming that there is a current user.
This line would also not display the current user if they are not in the first $limit number of entries
if($key + 1 > $limit)
break;
You can fix this by putting this after the code that looks for the current user.
In Java (I know, but its what I had running) it would look something like:
List<String> users = Arrays.asList("Brian","Tom","Jack","John");
int key = 0;
String html = "";
String currentUser = "Brian";
int limit = 3;
boolean foundCurrentUser = false;
for (String user : users) {
key ++;
if (currentUser == user) {
foundCurrentUser = true;
continue;
}
if (key > limit) {
continue;
}
html += user;
if (key < users.size() - 1) {
html += ",";
} else if (key == users.size() - 1 && key != limit) {
html += " and ";
}
}
if (foundCurrentUser) {
String userHTML = "You";
if (key > 2) {
userHTML += ", ";
} else if (key == 1) {
userHTML += " and ";
}
html = userHTML + html;
}
html = "Likeed by " + html;
if (users.size() > limit ) {
html += " and 3 other people";
}
System.out.println(html);

Categories