Лучший способ найти и заменить группу строк в другой строке в Java - PullRequest
0 голосов
/ 03 апреля 2012

Я ищу наилучший возможный подход для поиска и замены "группы строк" в другой строке. Группа строк постоянна [около 150 строк]. Текст для поиска является динамическим [около 10000 символов, около 2000 слов)

Группа 1: {"foo", "утка", "человек" ....., "xyz") [фиксированный набор - O (150)]

Группа 2: «Меня зовут Фу. У меня есть утка» [динамический текст - O (2000)]

Входной текст: меня зовут Фу. У меня есть утка.

Ожидаемый вывод текста: меня зовут *. У меня *.

Лучший подход, который я мог придумать, это ...

1) преобразовать группу 1 в HashSet

2) преобразовать динамический текст в строку []

3) Перебрать строку [] и проверить, существует ли строка в хэш-наборе.

for(int i = 0; i < String[].length; i++){
if(HashSet.contains(String[][i]))
 //Replace the string in the text
}

Есть ли лучшие альтернативы?

Пожалуйста, поделитесь своими мыслями ...

ОБНОВЛЕНО

Это окончательный код с выводом для замены группы строк в другой строке. (используя регулярное выражение)

public class StringReplacementTest
{

    private static final String[] restricted_words_list={"foo","duck","man","xyz"};
    private static final String[] not_restricted_words_list={"zoo","book","cool"};
    private static final Pattern restrictedReplacer;
    private static final Pattern nonRestrictedReplacer;
    private static Set<String> restrictedWords = null;
    private static List<String> nonRestrictedWords = null;


    static {//done once only

        StringBuilder strb= new StringBuilder();
        for(String str:restricted_words_list){
            strb.append("\\b").append(Pattern.quote(str)).append("\\b|");
            //using word break to avoid ***umptions;
        }
        strb.setLength(strb.length()-1);
        restrictedReplacer = Pattern.compile(strb.toString(),Pattern.CASE_INSENSITIVE);

        strb = new StringBuilder();
        for(String str:not_restricted_words_list){
            strb.append("\\b").append(Pattern.quote(str)).append("\\b|");
        }
        strb.setLength(strb.length()-1);
        nonRestrictedReplacer = Pattern.compile(strb.toString(),Pattern.CASE_INSENSITIVE);
    }


    /**
     * @param args
     */
    public static void main(String[] args)
    {
        String inputText = "My name is foo. I have a duck.. not ducks. I am FOO and the duckz at the zoo. i read book and COOL";
        System.out.println("inputText : " + inputText);
        String modifiedText = restrictedWordCheck(inputText);
        modifiedText =  nonRestrictWordCheck(modifiedText);
        System.out.println("Modified Text : " + modifiedText);
        System.out.println("List of restricted Words" + restrictedWords);
        System.out.println("List of non-restricted words" + nonRestrictedWords);
    }

    public static String restrictedWordCheck(String input){
        Matcher m = restrictedReplacer.matcher(input);
        StringBuffer strb = new StringBuffer(input.length());//ensuring capacity

        while(m.find()){
            if(restrictedWords==null)restrictedWords = new HashSet<String>();
            restrictedWords.add(m.group());  //m.group() returns what was matched
            m.appendReplacement(strb,""); //this writes out what came in between matching words
            for(int i=m.start();i<m.end();i++)
                strb.append("*");
        }
        m.appendTail(strb);
        return strb.toString();
    }

    public static String nonRestrictWordCheck(String input){

        Matcher m = nonRestrictedReplacer.matcher(input);
        while(m.find()){
            if(nonRestrictedWords==null)nonRestrictedWords = new ArrayList<String>();
            nonRestrictedWords.add(m.group());
        }
        return m.replaceAll("<b>$0</b>");  
    }
}

OUTPUT

inputText: Меня зовут Фу. У меня есть утка .. не утки. Я FOO и Duckz в зоопарке. я читаю книгу и классный

Измененный текст: Меня зовут . У меня * .. не уток. Я * и duckz в зоопарке . я читаю книгу и COOL

Список запрещенных слов [duck, foo, FOO]

Список неограниченных слов [zoo, book, COOL]

Любые советы по дальнейшей оптимизации реализации приветствуются:)

Спасибо

Ответы [ 2 ]

0 голосов
/ 03 апреля 2012

Это мой подход: Требуется:

        using System.Text.RegularExpressions;


        string group2 = "My name is foo. I have a duck";
        String[] group1 = {"foo","duck","man","xyz"};

        //Build the pattern 
        string pattern = "( "+group1[0];
        for(int i = 1;i<group1.Length;i++)
        {
            pattern += "|" + group1[i];
        }
        pattern += ")";

        //Apply it
        Regex a = new Regex(pattern);
        group2 = a.Replace(group2, "what you want to leave behind instead of any of the words");
0 голосов
/ 03 апреля 2012

использовать предварительно скомпилированный Pattern

private static final String[] arr={"foo","duck","man".....,"xyz"}
private static final Pattern replacer;
static {//done once only
    StringBuilder strb= new StringBuilder();
    for(String str:arr){
        strb.append("\\b").append(Pattern.quote(str)).append("\\b|");
        //using word break to avoid ***umptions;
    }
    strb.setLength(strb.length()-1);
    replacer = Pattern.compile(strb.toString());
}

public String replaceFoo(String in){
    return replacer.matcher(in).replaceAll("***");
}

вы можете усложнить то, что хотите заменить на

окружает слово тегами <b>: replacer.matcher(in).replaceAll("<b>$0</b>"); ($0 относится ко всему совпадению)

но если вы хотите сказать, совпадает с длиной совпадающей строки, вам придется явно зациклить ее:

Matcher m = replacer.matcher(in);
StringBuilder strb = new StringBuilder(in.length());//ensuring capacity

while(m.find()){
    m.appendReplacement(strb,"");//this writes out what came in between matching words
    //m.group() returns what was matched
    for(int i=m.start();i<m.end();i++)
        strb.append("*");
}
m.appendTail(strb);
return strb.toString;

но если вы хотите быть уверены в оптимальном времени выполнения, вы можете создать trie и запустить длинную строку на этом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...