最近我被问到这个问题,我无法找到最好的方法。我们正在尝试复制Google的搜索结果,其中搜索字词在结果中以粗体显示(使用b标记)。
Input Terms Output
The search is cool {sea} The <b>sea</b>rch is cool
最初,我认为这很简单:
String results(String input, String[] terms)
{
for(String term : terms)
{
input = input.replace(term, "<b>" + term + "</b>");
}
return input;
}
然而,这是不正确的。例如:
Input Terms Output
The search is cool {sea, search} The <b>search</b> is cool
我努力找出解决这个问题的最佳方法。显然我们不能再立即找到并替换。我使用的是Map<Integer,String>
,其中键是术语,值是input.indexOf(term)
返回的索引,但这似乎是不必要的。有什么改进?
public String results(String input, String[] terms)
{
Map<Integer, String> map = new HashMap<Integer,String>();
for(String term : terms)
{
int index = input.indexOf(term);
if(index >= 0)//if found
{
String value = map.get(index);
if(value == null || value.length() < term.length())//use the longer term
map.put(index, term);
}
}
for(String term: map.values())
{
input = input.replace(term, "<b>" + term + "</b>");
}
return input;
}
答案 0 :(得分:0)
试试这个
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.io.*;
public class main {
public static String results(String input, String[] terms)
{
for(String t : terms)
{
input = input.replace(t, "<b>" + t + "</b>");
}
return input;
}
public static void main(String[] args) {
String [] terms={"sea", "search"};
String s = results("The search is cool ",terms);
System.out.println(s);
String [] terms2={"search", "sea"};
String s2 = results("The search is cool ",terms2);
System.out.println(s2);
}
}
输出
The <b>sea</b>rch is cool
The <b><b>sea</b>rch</b> is cool
在您的代码中,您在哈希映射中的相同索引中添加了两次字符串,因此实际上它在哈希映射本身中将“sea”替换为“search”。因为在两种情况下索引都是4。
Map<Integer, String> map = new HashMap<Integer,String>();
for(String term : terms)
{
int index = input.indexOf(term);
if(index >= 0)//if found
{
String value = map.get(index); //the index is 4 here both the times
if(value == null || value.length() < term.length())
map.put(index, term);//so first time putting string sea at index 4 and in second iteration replacing "sea" to "search" at the same index 4 in hashmap because you want a longer term
}
}
for(String term: map.values())//here getting only one string which is "search"
{
input = input.replace(term, "<b>" + term + "</b>");
}
但是,如果你想要一个比你的代码本身工作得更好的更长期。
答案 1 :(得分:0)
你可以用正则表达式来做。
public static String results(String input, String[] terms) {
String output = input;
Arrays.sort(terms);
for (int i = terms.length - 1; i >= 0; --i) {
String term = terms[i];
output = output.replaceAll("(?<!>)\\b" + term, "<b>" + term + "</b>");
}
// With regular expressions.
// \\b = word boundary, starting at words
// (?<X) = without preceding X (negative look-behind)
// Converting " searching " to " <b>search</b>ing ",
// Not converting " research ".
return output;
}
解决方案是反向排序,因此&#34;搜索&#34;在&#34; sea&#34;之前,检查没有&#34;&gt;&#34;在单词之前(=已经替换;具有较长期限)。
我添加了一个单词边界检查,也就是说,术语应该在单词的开头。没必要。
请注意,数组参数terms
已排序。