使用子字符串结果查找并替换String

时间:2014-03-28 16:47:31

标签: java string map

最近我被问到这个问题,我无法找到最好的方法。我们正在尝试复制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;
}

2 个答案:

答案 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已排序。