【问题标题】:Find and replace String with a substring result用子字符串结果查找并替换字符串
【发布时间】:2014-03-28 16:47:30
【问题描述】:

最近有人问我这个问题,但我想不出最好的方法。我们正在尝试复制 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&lt;Integer,String&gt;,其中键是术语,值是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;
}

【问题讨论】:

  • 如果它已经在工作,你应该把它发布到codereview.stackexchange.com。
  • 先将术语从最短到最长排序并删除重复项,然后执行此操作!

标签: java string map


【解决方案1】:

试试这个

  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>");
}

但是,如果您想要更长的期限,那么它在您的代码本身中可以正常工作。

【讨论】:

    【解决方案2】:

    你可以用正则表达式来做。

    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;
    }
    

    解决方案是反向排序,因此“search”在“sea”之前,并检查单词之前是否没有“>”(= 已替换;具有更长的术语)。

    我添加了一个单词边界检查,即术语应该在单词的开头。没必要。

    注意数组参数terms 已排序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-28
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多