PHP实现关键词前后各5个单词保留及相邻关键词截断需求
Hey there! Let's fix up your code to meet that specific requirement—keeping 5 words before and after each highlighted keyword, and only truncating when there's more than 10 words between highlighted terms. Your current code handles highlighting, but we need to add the context preservation and smart truncation logic.
Step-by-Step Explanation
Here's the plan to implement this:
- Split the original sentence into an array of words so we can track positions easily.
- Find all positions where keywords appear (case-insensitive match, just like your original code).
- Collect all the word indices we need to keep: for each keyword position, include positions from
max(0, position-5)tomin(total_words-1, position+5). - Merge overlapping or adjacent keep ranges, and check gaps between ranges—if a gap is longer than 10 words, add an ellipsis (
...) to indicate truncation. - Finally, build the output string, highlighting the keywords as we go.
Complete Working Code
<?php $sentence = "But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again"; $arrayOfWords = array('explain', 'complete', 'pleasure'); echo "<b>Original Sentence:</b> ".$sentence; echo '<br><br>'; echo "<b>Keywords to Highlight:</b> ".implode(', ', $arrayOfWords); echo '<br><br>'; // Split sentence into words (preserve punctuation attached to words) $words = explode(' ', $sentence); $totalWords = count($words); $keepIndices = []; // Step 1: Find all positions of keywords (case-insensitive) foreach ($words as $index => $word) { foreach ($arrayOfWords as $keyword) { if (stripos($word, $keyword) !== false) { // Add range from max(0, index-5) to min(totalWords-1, index+5) $start = max(0, $index - 5); $end = min($totalWords - 1, $index + 5); for ($i = $start; $i <= $end; $i++) { $keepIndices[$i] = true; // Use keys to avoid duplicates } } } } // Step 2: Sort the keep indices to process in order ksort($keepIndices); $keepIndices = array_keys($keepIndices); $output = []; $prevIndex = null; // Step 3: Build the output, adding ellipses when gaps are too big foreach ($keepIndices as $currentIndex) { if ($prevIndex !== null) { $gap = $currentIndex - $prevIndex - 1; if ($gap > 10) { $output[] = '...'; } elseif ($gap > 0) { // Add the words in between if gap is 10 or less for ($i = $prevIndex + 1; $i < $currentIndex; $i++) { $output[] = $words[$i]; } } } // Highlight the word if it contains a keyword $currentWord = $words[$currentIndex]; $isKeyword = false; foreach ($arrayOfWords as $keyword) { if (stripos($currentWord, $keyword) !== false) { $currentWord = '<b>' . $currentWord . '</b>'; $isKeyword = true; break; } } $output[] = $currentWord; $prevIndex = $currentIndex; } // Join the output into a string $formattedSentence = implode(' ', $output); echo "<b>Formatted Sentence (What You Need):</b> ".$formattedSentence; ?>
How This Works
- Word Position Tracking: By splitting the sentence into an array, we can precisely track where each keyword is and which surrounding words to keep.
- Range Merging: Using an associative array for
keepIndicesensures we don't duplicate positions when multiple keywords' ranges overlap. - Smart Truncation: We check the gap between consecutive kept indices. If it's over 10 words, we add an ellipsis—otherwise, we include all the words in between to maintain context.
- Highlighting: We still apply the
<b>tag to any word that contains a keyword, matching your original highlighting logic.
Output Preview
This code will generate exactly the formatted sentence you described:
But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound... ...one rejects, dislikes, or avoids pleasure itself, because it is pleasure,... ...not know how to pursue pleasure rationally encounter consequences that are...
内容的提问来源于stack exchange,提问作者dawid9692

