Sorting search results array by number of matches? - php

I'm building a basic search function for my site. Realising that the most useful search displays the page with the most counts of the terms given, I coded the following:
function search()
{
$this->page = preg_replace('/[^\w \"\']/i', '', trim($this->page));
preg_match_all('/"(.[^"]+)"|([\w]+)/i', $this->page, $terms);
$terms=array_unique($terms[0]); // scrub duplicate search terms
$tsql="SELECT reviewSummary, reviewFullText, game.gameName FROM review LEFT JOIN game ON review.gameID = game.gameID ";
$constraint="WHERE";
foreach ($terms as $term)
{
$term=str_replace('"','',$term);
$tsql.=" $constraint (reviewSummary LIKE '%".$term."%' OR reviewFullText LIKE '%".$term."%' OR game.gameName LIKE '%".$term."%')";
$constraint="AND";
}
$tsql .= "AND game.isPublished = 'y'";
$result = $this->sql->db_query($tsql);
if (mysql_num_rows($result)!=0)
{
while($row = mysql_fetch_array($result))
{
$gameName = stripslashes($row['gameName']);
$content = strip_tags($row['reviewFullText']) . ' ' . $row['reviewSummary'];
$counter = 0;
foreach($terms as $term)
{
$term=str_replace('"','',$term);
preg_match_all("/($term)/i", $content, $matches);
foreach($matches[0] as $m)
{
$counter++;
}
}
$found["Games"][$gameName]=$counter;
}
}
print_r($found);
}
Works great. What it doesn't do is order the results in according to which has the most matches. I'm not sure how to sort the resulting array to achieve this, can anyone help?

Take a look at at uasort() which can sort an associative array using a user-defined comparison function. Something like this should do it...
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a < $b) ? 1 : -1;
}
uasort($found["Games"], 'cmp');

Related

Order array of sentences by an array containing words / searchterms

I have an array of sentences that I retrieve from an MYSQL database based on an array of words:
$queryTitles = '
SELECT title
FROM `#__items`
WHERE `title` REGEXP "'.$search.'" AND `published`=1';
Where $search contains the REGEXP:
foreach ($searchword as $key => $value) {
if ($key === array_key_last($searchword)) {
$search .= '' . $db->escape( $value, true ) . '';
break;
}
$search = '' . $db->escape( $value, true ) . '|';
}
Now I get this list of titles back which contains the words in the $search words. But I'd like to order these list of titles based on the amounts of words found in the array.. But I'm not sure how to do that.
Maybe with usort?
usort($dataCat, function ($a, $b) {
$countA=0;
$countB=0;
foreach ($searchword as $value) {
if(checkIfContains($a, $value )){
$countA++;
}
if(checkIfContains($a, $value )){
$countB++;
}
}
if ($countA == $countB) {
return 0;
}
return ($countA < $countB) ? -1 : 1;
});
But this doesn't work... Anyone know what I am doing wrong?

Filtering search engine data

I have a problem with filtering information using a form,
Here is my code
$cooperation = Cooperation::with('user')->get();
$search_results = [];
$search = Input::get('q');
$category = Input::get('c');
$land = Input::get('l');
if(!empty($search || $category || $land)){
$search_results = $cooperation;
if (!empty($search)){
$search_results = $search_results->where('title', 'like', '%'. $search .'%');
}
if (!empty($category)){
$search_results = $search_results->where('category', $category);
}
if (!empty($land)){
$search_results = $search_results->where('land', $land);
}
$exist_s = true;
$not_s = false;
return view('cooperation.index', compact('cooperation', 'search_results', 'exist_s', 'not_s'));
}
else{
$not_s = true;
$exist_s = false;
return view('cooperation.index', compact('cooperation', 'search_results', 'exist_s', 'not_s'));
}
After retrieving data from the form I am trying to filter through the array in sequence by each variable but nothing happens, the only thing that works is filtering in $ category but I do not know why the rest does not work.
I'm looking for a solution as to how to filter data efficiently, I could do it if () after if () but with more variables it would be a very inefficient solution.
If anyone has any idea in advance thank you.
If you want to have an efficient search according to your requirements you can have following input variables:
$columns, $searchColumns, $search_operator, $search_input
$columns can be the columns through which you can order, searchColumns can be the columns through which you want to have search and search_operator as in like, <, <=, in, >, >= etc, you can even improvise with the direction as asc or dsc in values, so you can have something like this:
return $query
->orderBy($request->column, $request->direction)
->where(function($query) use ($request, $searchColumns) {
if($request->has('search_input')) {
for($x = 0, $l = count($searchColumns); $x < $l; $x++) {
if($request->search_operator == 'in') {
$query->whereIn($searchColumns[$x], explode(',', $request->search_input));
} else if($request->search_operator == 'like') {
$query->orWhere($searchColumns[$x], 'LIKE', '%'.$request->search_input.'%');
}
else {
$query->orWhere($searchColumns[$x], $this->operators[$request->search_operator], $request->search_input);
}
}
}
})
->paginate(100);
I don't know why your request is not working. However, if you are looking for a generic way of filtering your results I believe a simple foreach loop with an array of your filters variables would do the trick :
$filters = []; //your variables such as category and land go in there
foreach ($filters as $column => $value){
$search_results = $search_results->where($column, $value);
}

extract values found in array from string

I am stuck. What I would like to do: In the $description string I would like to check if any of the values in the different arrays can be found. If any of the values match, I need to know which one per array. I am thinking that I need to do a function for each $a, $b and $c, but how, I don't know
if($rowGetDesc = mysqli_query($db_mysqli, "SELECT descFilter FROM tbl_all_prod WHERE lid = 'C2'")){
if (mysqli_num_rows($rowGetDesc) > 0){
while($esk= mysqli_fetch_array($rowGetDesc)){
$description = sanitizingData($esk['descFilter']);
$a = array('1:100','1:250','1:10','2');
$a = getExtractedValue($a,$description);
$b = array('one','five','12');
$b = getExtractedValue($b,$description);
$c = array('6000','8000','500');
$c = getExtractedValue($c,$description);
}
}
}
function getExtractedValue($a,$description){
?
}
I would be very very greatful if anyone could help me with this.
many thanks Linda
It would be better to create each array just once and not in every iteration of the while loop.
Also using the same variable names in the loop is not recommended.
if($rowGetDesc = mysqli_query($db_mysqli, "SELECT descFilter FROM tbl_all_prod WHERE lid = 'C2'")){
if (mysqli_num_rows($rowGetDesc) > 0){
$a = array('1:100','1:250','1:10','2');
$b = array('one','five','12');
$c = array('6000','8000','500');
while($esk= mysqli_fetch_array($rowGetDesc)){
$description = sanitizingData($esk['descFilter']);
$aMatch = getExtractedValue($a,$description);
$bMatch = getExtractedValue($b,$description);
$cMatch = getExtractedValue($c,$description);
}
}
}
Use strpos to find if the string exists (or stripos for case insensitive searches). See http://php.net/strpos. If the string exists it will return the matching value in the array:
function getExtractedValue($a,$description) {
foreach($a as $value) {
if (strpos($description, $value) !== false) {
return $value;
}
}
return false;
}
there s a php function for that which return a boolean.
or if you wanna check if one of the element in arrays is present in description, maybe you 'll need to iterate on them
foreach($array as element){
if(preg_match("#".$element."#", $description){
echo "found";
}
}
If your question is correctly phrased and indeed you are searching a string, you should try something like this:
function getExtractedValue($a, $description) {
$results = array();
foreach($a as $array_item) {
if (strpos($array_item, $description) !== FALSE) {
$results[] = $array_item;
}
}
return $results;
}
The function will return an array of the matched phrases from the string.
Try This..
if ( in_array ( $str , $array ) ) {
echo 'It exists'; } else {
echo 'Does not exist'; }

Find the longest array value from given search ID

I have two arrays, one with a large set of URL paths and another with search IDs. Each of the URL paths has one unique ID in common. By the search ID we need to find the longest URL with the unique ID. Here is my code, I will explain a bit more later.
<?php
function searchstring($search, $array) {
foreach($array as $key => $value) {
if (stristr($value, $search)) {
echo $value;
}
}
return false;
}
$array = array(
"D:\winwamp\www\info\961507\Good_Luck_Charlie",
"D:\winwamp\www\info\961507\Good_Luck_Charlie\season_1",
"D:\winwamp\www\info\961507\Good_Luck_Charlie\season_1\episode_3",
"D:\winwamp\www\info\961507\Good_Luck_Charlie\season_1\episode_3\The_Curious_Case_of_Mr._Dabney",
"D:\winwamp\www\info\961506\Good_Luck_Charl",
"D:\winwamp\www\info\961506\Good_Luck_Charlie\season_1",
"D:\winwamp\www\info\961506\Good_Luck_Charlie\season_1\episode_1",
"D:\winwamp\www\info\961506\Good_Luck_Charlie\season_1\episode_1\Study_Date");
$searchValues = array("961507","961506");
foreach($searchValues as $searchValue) {
$result = searchstring($searchValue, $array);
}
?>
This gives the value of all matched IDs. Now if you see my array there are four sets of URL paths. What I want is that if I search with "961507" it should give:
"D:\winwamp\www\info\961507\Good_Luck_Charlie\season_1\episode_3\The_Curious_Case_of_Mr._Dabney"
If i search with "961506", it should give:
"D:\winwamp\www\info\961506\Good_Luck_Charlie\season_1\episode_1\Study_Date"
Now what I am getting are all the arrays that matched with my searched ID. Can you please help me to find out how can I accomplish this? Because I have more than 98000 URLs to sort out.
Change the function as
function searchstring($search, $array) {
$length = 0;
$result = "";
foreach($array as $key => $value) {
if (stristr($value, $search)) {
if($length < strlen($value)) {
$length = strlen($value);
$result = $value;
}
}
}
return $result;
}
To print value use:
foreach($searchValues as $searchValue) {
$result = searchstring($searchValue, $array);
echo $result;
}
Or
$result = array();
foreach($searchValues as $searchValue) {
$result[] = searchstring($searchValue, $array);
}
print_r($result);

PHP count # of items in an object of a given property value

How can I count the number of items with the same folder_id# ?
Here's my list of items:
item_id=1, folder_id=1
item_id=2, folder_id=1
item_id=3, folder_id=2
item_id=4, folder_id=3
Here's my UPDATED code:
foreach($items as $item)
{
if(????) //count of $item->folder_id > 1
{
//do something to $item->folder_id=1/$item->item_id=1
}
elseif(????) // cases where $item->item_id != $item->folder_id
{
//do something else to $item->folder_id=1/$item->item_id=2
}
else
{
//do something else to $item->folder_id=2/$item->item_id=3 and folder_id=3/item_id=4
}
}
I'm interested in code that can tell me that the count for folder_id=1 is 2, the count for folder_id=2 is 1, and the count for folder_id=3 is also 1.
UPDATE: I've changed the code above to now include an elseif() because it didn't quite ask all the things I was interested in. Besides counting the # of each folder_id, I'm also interested in distinguishing cases where folder_id != item_id. This would put item_id=1, item_id=2, item_id=3/4 in their own conditional clauses and wouldn't lump item_id=1 and item_id=2 as before.
Any assistance would be greatly appreciated, thank you,
If you had an array of folder_ids, you could use array_count_values to provide exactly the result you need. So let's make an array like that out of an array of objects using array_map:
$callback = function($item) { return $item->folder_id; };
$result = array_count_values(array_map($callback, $items));
This will end up with $result being
array(
1 => 2,
2 => 1,
3 => 1,
);
You can also write the callback inline for an one-liner, or if you are on PHP < 5.3 you can write it as a free function or alternatively using create_function.
See it in action (version for PHP < 5.3).
Update: follow up
Given $results from above, your loop would be:
foreach($results as $folder_id => $count) {
if($count > 1) {
// There were $count items with folder_id == $folder_id
}
// else blah blah
}
$totals = array();
foreach($items as $item) {
$totals[$item->folder_id]++;
}
function count_items(Array $items, $folder_id) {
return count(array_filter($items,
function($item) use($folder_id) {
return $item->folder_id === $folder_id;
}
));
}
I think this is what you are looking for.
function folder_count($items, $num)
{
$cnt = 0;
foreach($items as $item)
{
if($item->folder_id > $num)
{
$cnt++;
}
}
return $cnt;
}
foreach ($items as $item)
{
if (folder_count($items, 1))
{
//do something to $item->folder_id=1/$item->item_id=1, item_id=2
}
else
{
//do something else to $item->folder_id=2/$item->item_id=3 and folder_id=3/item_id=4
}
}

Categories