Add +1 to each index found in an array - php

I have a form that takes in a users input and puts it in an array, the user then chooses a word they want to find in said array. Thereafter the array is checked to see what each index of the word is as well as each occurrence of the word in the text.
So if you write the string "What is what" and want to find the word "what" it will say that the position of the word is "0 and 2" whereas I'd like it to say "1 and 3". How do I go about this?
Here's the code:
<form action="sida3.php" method="post">
Text: <textarea name="textarea"></textarea>
<br> Search word: <input type="text" name="search">
<br>
<input type="submit" name="submit" value="Submit">
</form>
<?php
if(isset($_POST['submit'])){
$parts = explode(" ", $_POST['textarea']);
$strName = $_POST['search'];
print_r ($parts);
echo '<br>';
foreach($parts as $item) {
if ($item == $strName) {
$counter++;
}
}
echo "The word $strName can be found at: ";
echo implode(' ', array_keys($parts, $strName));
echo "<br>";
echo "The word $strName was found $counter times";
}

I'm not sure what you're doing with the foreach or if that's where you want to create the positions, but:
foreach($parts as $pos => $item) {
if ($item == $strName) {
$result[] = $pos + 1;
}
}
Then just:
echo implode(' ', $result);

You can map +1 over the array keys before imploding. I also suggested another way to find the search term and count the occurrences, if you're interested in that, but map will work with the way you're currently doing it as well.
$found = array_intersect($parts, [$strName]);
echo "The word $strName can be found at: ";
echo implode(' ', array_map(function($x) { return $x + 1; }, array_keys($found)));
echo "<br>";
echo "The word $strName was found ". count($found) ." times";

You can use array_combine to combine a range from 1 to count of the array with the values.
$str = "This is a string.";
$arr = explode(" ", $str);
$range = range(1,count($arr)); // creates a range from 1 -> count of $arr
$new = array_combine($range, $arr); // sets the range as the key and $arr as the value
var_dump($new);
https://3v4l.org/SUhVM
Now that I look at the question again I see that there is a big flaw we all have missed.
If the word you search for is next to a dot, comma or other symbol it won't be counted.
Here I use the code I had in the answer above but added preg_replace to remove all characters that is not a-Z 0-9 (meaning english alphabet, change to suit your needs).
I then use substr_count to find the number of words without looping.
I use array_intersect to reduce the array to only the items matching $find, and grab the keys with array_keys. The key is the positions of the words.
All done without looping.
$str = "This is a car. Automobile (car) is another word for it. You can also add a hashtag, #car";
$find = "car";
$count = substr_count($str, $find);
$str = preg_replace("/[^a-zA-Z 0-9]/", "", $str);
$arr = explode(" ", $str);
$range = range(1,count($arr));
$new = array_combine($range, $arr);
$positions = array_keys(array_intersect($new, [$find]));
echo $find . " was found " . $count . " times. At positions: " . implode(", ", $positions);
Just looping and matching with == will only find one car in this string.
https://3v4l.org/sHAd5

Related

Highlighting strings with different orders in PHP

I am trying to highlight the strings. Whether they are in the sequence or not.
Like this -
$str = "star 5 hotel";
$keywords = "5 star hotels";
There is my function. It only highlights the last matching string.Here $str contains the search string. $keyword contains that string which i have stored into database
How can i highlight each matching string.
function highlight($str, $keyword) {
$str = "star hotel 5";
$keyword = "5 star hotel";
foreach($look as $find){
if(strpos($keyword, $find) !== false) {
if(!isset($highlight)){
$highlight[] = $find;
} else {
if(!in_array($find,$highlight)){
$highlight[] = $find;
}
}
}
}
if(isset($highlight)){
foreach($highlight as $replace){
$str = str_ireplace($replace,'<b>'.$replace.'</b>',$keyword);
$stra[] = str_ireplace($replace,'<b>'.$replace.'</b>',$keyword);
echo "<pre>";
print_r ($stra);
echo "</pre>";
}
}
echo $str."<br>";
die();
return $str;
}
But when i put this into an array and when i print this array $stra[]. It given me this
Array
(
[0] => 5 star hotel
[1] => 5 star hotel
[2] => 5 star hotel
)
I can not find way to combine these.
Output : -If have that keyword which is searching . then this must be Highlighted..
5 star hotel
This is what I assumed:-
I assume that you want to search each word of the search sting in the given string and if and only if all the words found then make string in bold (complete string).
Then do like below (Explanation given in comments):-
<?php
$search = "star 5 hotel"; //search string
$string = "5 star hotels"; // string in which you want to search
function highlight($search, $string) {
$new_search = array_unique(array_filter(explode(" " ,$search)));//explode search string
$found_count = 0; //create a counter
foreach($new_search as $find){ // iterate over search words array
if(strpos($string, $find) !== false) { // if word found in the string
$found_count +=1; // increase the counter
}
}
if(count($new_search) == $found_count){ //check that all words found in the string
$string = "<b>". $string ."</b>"; // if yes then make each word of the string bold
}
return $string; //return the newly modified string
}
echo highlight($search, $string); // echo newly modified string
Output:- https://eval.in/838325
You can use an array, and strtr() function. :)
$str = "the quick brown fox";
$keywords = "quick fox brown";
$matches = explode(" ",$keywords);
foreach ($matches as $v) {
$arr_matches[$v] = "<b>".$v."</b>";
}
$str = strtr($str, $arr_matches);
I know it's late but here is one way to make a double loop that will keep the bloat tags to a minimum and handle extra words in the sentence (in what I think is correct way).
It checks if the word is in match list, if yes loop til there is a not matching word.
Add the tags around those two words and go back to main loop.
$str = "star 5 hotel";
$strarr =explode(" ", $str);
$keywords = "a 5 star uinique hotel";
$arr = explode(" ", $keywords);
For($i=0; $i < count($arr) ; $i++){
If(in_array($arr[$i], $strarr)){
$j=$i;
While(in_array($arr[$j], $strarr) && $j < count($arr)){
$j++;
}
$j--;
$arr[$i] = "<b>" . $arr[$i];
$arr[$j] = $arr[$j] . "</b>";
$i=$j;
}
}
Echo implode(" ", $arr);
Output of above example:
a <b>5 star</b> uinique <b>hotel</b>
https://3v4l.org/pKE4X
You can use an array to achieve:
$str = 'This is some 5 start hotel in US';
$keyWords = ['5', 'star', 'hotel'];
$strToCheck = explode(' ', $str);
foreach ($keyWords as $k => $v)
{
if (in_array($v, $strToCheck)) {
//do something
}
}
this creates the string as an array, this means we can use in_array to check, then inside the if statement do whatever :)
references:
http://php.net/manual/en/function.in-array.php
http://php.net/manual/en/function.explode.php
Why don't you just iterate over your keywords and replace them:
$str = "This is a star 5 hotel located in New York";
$keywords = array("5","star","hotels");
foreach (array_expression as $key => $value){
$str = str_replace($value, "<b>".$value."</b>", $str);
}
Simple and failsafe if you don't have double keywords.
Or if your keywords need to be a something-separated string:
$str = "This is a star 5 hotel located in New York";
$keywords = "5 star hotel";
$arraykeywords = explode(" ",$keywords);
foreach (array_expression as $key => $value){
$str = str_replace($value, "<b>".$value."</b>", $str);
}
To filter double keywords use array_unique:
$str = "This is a star 5 hotel located in New York";
$keywords = "5 star hotel star";
$arraykeywords = array_unique(explode(" ",$keywords));
foreach (array_expression as $key => $value){
$str = str_replace($value, "<b>".$value."</b>", $str);
}
After a lot of discussion about regex (see the comments), this is the approach using #Andreas's regex:
$str = "This is a star 5 hotel located in New York";
$keywords = "5 star hotel star";
$pregsearch = "/".implode("|",array_unique(explode(" ",$keywords)))."/g"; //remove dups and join as regex
$str = preg_replace($pregsearch, "<b>$0</b>", $str);
Only recomended if your searching a large string.

Replacing a string while choosing the order in which the part of strings get replaced first

I'm trying to replace a string with certain words, but I also want to replace it in order of the position in the array. For example, I want to replace "b c", before I try to replace "a b", without changing the position in the original string. By the way, the letters are suppose to represent actual words, and they are not supposed be part of another word. For example, the word "sun" is part of "sunflower", and the word "sunflower" cannot be replaced just because the word "sun" is in it.
$text = "a b c";
$replacement = array("a b" => "ab","b c" => "bc");
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
echo $text = preg_replace_callback("/\b(" . implode("|", $search) . ")\b/", function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
First Result
ab c
Second Result
I switched the position in the array around, thinking that it would affect the order of which the strings get replaced. Sadly, it doesn't work like that, and I got the same result.
$replacement = array("b c" => "bc","a b" => "ab");
ab c
At this point, I realize that it wasn't the position of the array that affects which part of the string that get replaced first, but the order of the part of strings that shows up on the original string that determines the order in which it is replaced by.
So, my question is, is there a way to somehow make it so that it can replace the string in order according to the order in which it is in the array, or in a different way? For example, I want to replace
"b c"
before I try to replace "a b" without changing the position of the original string. Is that doable? Thanks.
[EDIT]
The idea consists to cast the original text to an array (with one element at the beginning, the text). Array items at even index are splitted for each patterns. Since PREG_SPLIT_DELIM_CAPTURE option is used, delimiters have always an odd index and stay untouched once they are matched.
$text = 'a b c';
$rep = ['b c'=>'bc', 'a b'=>'ab', ];
$pats = array_map(function($i) {
return '~\b(' . preg_quote($i, '~') . ')\b~';
}, array_keys($rep));
$parts = (array)$text; // or $parts = [ $text ]; // it's the same
foreach ($pats as $pat) {
$temp = [];
foreach ($parts as $k=>$part) {
if ($k & 1)
$temp[] = $part;
else
$temp = array_merge(
$temp,
preg_split($pat, $part, -1, PREG_SPLIT_DELIM_CAPTURE)
);
}
$parts = $temp;
}
$result = '';
foreach ($parts as $k=>$part) {
$result .= ($k & 1) ? $rep[$part] : $part;
}
echo $result;
I changed your code to represent what (I think) you wanted:
$text = "a b c a b";
$replacement = array("b c" => "bc", "a b" => "ab");
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
for($i = 0; $i < count($replacement); $i++) {
$regex = "/\b(" . $search[$i] . ")\b/";
echo $text = preg_replace_callback($regex, function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
echo "<br>";
}
Basically, instead of relying on the regex to do that work I do a for loop to go through each replacement and create the regex. That way the order of the array matters. I also changed the initial $text to test if it worked

PHP get words with length longer than 3 from string

Is there a function that can cut words from a string that are small length e.g. "the, and, you, me, or" all these short words that are common in all sentences. i want to use this function to fill a fulltext search with criteria
before the method:
$fulltext = "there is ongoing work on creating a formal PHP specification.";
outcome:
$fulltext_method_solution = "there ongoing work creating formal specification."
$fulltext = "there is ongoing work on creating a formal PHP specification.";
$words = array_filter(explode(' ', $fulltext), function($val){
return strlen($val) > 3; // filter words having length > 3 in array
});
$fulltext_method_solution = implode(' ', $words); // join words into sentence
try this:
$fulltext = "there is ongoing work on creating a formal PHP specification.";
$result=array();
$array=explode(" ",$fulltext);
foreach($array as $key=>$val){
if(strlen($val) >3)
$result[]=$val;
}
$res=implode(" ",$result);
You can simply use implode, explode along with array_filter
echo implode(' ',array_filter(explode(' ',$fulltext),function($v){ return strlen($v) > 3;}));
or simply use preg_replace as
echo preg_replace('/\b[a-z]{1,3}\b/i','',$fulltext);
try this:
$stringArray = explode(" ", $fulltext);
foreach ($stringArray as $value)
{
if(strlen($value) < 3)
$fulltext= str_replace(" ".$value." " ," ",$fulltext);
}
Here is a working DEMO
Simply explode the string and check for the strlen()
$fulltext = "there is ongoing work on creating a formal PHP specification.";
$ex = explode(' ',$fulltext);
$res = '';
foreach ($ex as $txt) {
if (strlen($txt) > 3) {
$res .= $txt . ' ';
}
}
echo $res;
By using preg_replace
echo $string = preg_replace(array('/\b\w{1,3}\b/','/\s+/'),array('',' '),$fulltext);
This will also produce the desired results:
<?php
$fulltext = "there is ongoing work on creating a formal PHP specification.";
$fulltext = preg_replace('/(\b.{1,3}\s)/',' ',$fulltext);
echo $fulltext;
?>

Trying to spit sentence into array with words

I am trying to split a sentence into an array with words, one word as each element, in PHP if there is more than one word in the sentence. If there is only one word in the sentence, then I just print that one word.
My issue is when I split the sentence into words delimited by a space and put the contents into an array. I do this all using explode. But when I run through the array that explode apparently makes, it says there is nothing in the array when I try to print each item.
Here is my code:
if(isset($_GET['check'])){
$input = trim($_GET['check']);
$sentence='';
if(stripos($input, ' ')!==false){
$sentence = explode(' ', $input);
foreach($sentence as $item){
echo $item;
}
}
else{
echo $input;
}
}
Why is echo $item; printing nothing? Why isn't there anything in the array $sentence?
Your code seems to be working fine. Make sure you're getting the variable. You can do a print_r($_GET);
You can also just do this:
<?php
$_GET['check'] = 'Hey how are you?';
if (isset($_GET['check'])) {
// each word is now an element in the array
$arr = explode(' ', trim($_GET['check']));
}
// piece each word back together with a space
echo implode(' ', $arr);
?>
It doesn't matter if it's a single word or multiple words.
UPDATE: If you really want to check if the user has entered one word or more than one word you can do this:
<?php
$_GET['check'] = 'Hey how are you?';
if (str_word_count($_GET['check']) > 1) {
echo 'More than one word';
} else {
echo 'Only one word';
}
?>
Check out str_word_count

Sort the contents of the textfile in ascending

I am trying to develop a code that will sort the contents of the text file in ascending order. I have read the contents of the file and was able to display the texts.
I am having difficulty sorting them out in from low to high order, word by word.
I have tried the asort from php.net, but just could not get the code to work well.
thanks.
To answer your second question, you can read the text file into into a variable (like you've said you have already), eg. $variable, then use explode (http://php.net/manual/en/function.explode.php) to separate, at each space, each word into an array:
//$variable is the content from your text file
$output = explode(" ",$variable); //explode the content at each space
//loop through the resulting array and output
for ($counter=0; $counter < count($output); $counter++) {
echo $output[$counter] . "<br/>"; //output screen with a line break after each
} //end for loop
If your paragraph contains commas etc which you don't want to output you can replace those in the variable before exploding it.
//Split file by newlines "\n" into an array using explode()
$file = explode("\n",file_get_contents('foo.txt'));
//sort array with sort()
sort($file);
//Build string and display sorted contents.
echo implode("\n<br />",$file);
Sort functions needs to have an array as argument, make sure your file is in an array. asort is for associative arrays, so unless you need to keep the array keys you can use sort instead.
$file = "Hello world\ngoodbye.";
$words = preg_split("/\s+/", $file);
$clean_words = preg_replace("/[[:punct:]]+/", "", $words);
foreach ($clean_words as $key => $val) {
echo "words[" . $key . "] = " . $val . "\n";
}
--output:--
words[0] = Hello
words[1] = world
words[2] = goodbye
sort($clean_words, SORT_STRING | SORT_FLAG_CASE);
foreach ($clean_words as $key => $val) {
echo "words[" . $key . "] = " . $val . "\n";
}
--output:--
words[0] = goodbye
words[1] = Hello
words[2] = world
Try this
<?php
$filecontent = file_get_contents('exemple.txt');
$words = preg_split('/[\s,.;":!()?\'\-\[\]]+/', $filecontent, -1, PREG_SPLIT_NO_EMPTY);
$array_lowercase = array_map('strtolower', $words);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $words);
foreach($words as $value)
{
echo "$value <br>";
}
?>

Categories