Java Как разобрать нотации Smile из строки

Я хочу проанализировать строку, которая включает в себя эмоциональные обозначения, такие как ":)",":p","!","?", а также слова. Например, как эта строка "How dare you! You have lost him two days ago:'(", я хочу получить такой результат:

How
dare
you
!
You
have
lost
him
two
days
ago
:'(

Я использую StringTokenizer для разбора предложений с разделителем, но я потерял эмоциональные обозначения. Спасибо

Код, который я использую:

public class FullParser {
    private String sentence;
    private String separator="' ,.:!()@/<>";

    private ArrayList<String> mywords;

    public FullParser(String sentence){
        this.sentence=sentence;
        mywords=new ArrayList<String>();
        separator+='"';
    }
    public void parsing(){
        StringTokenizer st = new StringTokenizer( sentence, separator, true );

        while ( st.hasMoreTokens() ) {
            String token = st.nextToken();
            if (!( token.length() == 1 && separator.indexOf( token.charAt( 0 ) ) >= 0 )) {
                //Log.i("PARSER",token);                
                mywords.add(token);
            }
        }
    }
    public ArrayList<String> getmyWords(){
        return mywords;
    }

person reigeki    schedule 17.05.2013    source источник
comment
Покажите нам код. Обратите внимание, что разделителем по умолчанию является пробел. Однако вы можете использовать свой собственный: StringTokenizer st = new StringTokenizer(text, "......");   -  person Maroun    schedule 17.05.2013
comment
Как вы хотите обрабатывать пунктуацию?   -  person zEro    schedule 17.05.2013


Ответы (3)


Я не уверен, ответит ли это на ваш вопрос, но просто чтобы продемонстрировать силу регулярных выражений, вот однострочное решение: (достаточно проверено)

sentence.split(" |(?<! |\\p{Punct})(?=\\p{Punct})|(?<=\\p{Punct})(?!\\p{Punct})");

\\p{Punct} используется для любого одиночного знака пунктуации, или, если вы хотите быть более точным, вы также можете использовать [',\\.:!()@/<>], что означает любой из этих символов: ',\\.:!()@/<>.
(?<!...) означает отрицательный просмотр назад, то есть предыдущие символы не соответствует этому.
(?=...) означает положительный просмотр вперед, то есть следующие символы соответствуют этому.
(?<=...) означает положительный просмотр назад, что означает, что предыдущие символы соответствуют этому.
(?!...) означает отрицательный просмотр вперед, что означает следующий символы не соответствуют этому.
Пробел является фактическим пробелом.
| означает "ИЛИ", например, то, что появляется слева ИЛИ то, что появляется справа до ближайшей закрывающей скобки.

Почему это работает, нужно хорошенько подумать.

Мне пришлось усложнить это немного больше, чем мне бы хотелось, потому что были некоторые случаи, которые не работали.

Тест.

См. это для получения дополнительной информации о Java. обычные выражения.

person Bernhard Barker    schedule 17.05.2013
comment
public static void main(String[] args) throws Exception { String string = Сегодня она идет на пляж :DD ‹3; Строковое регулярное выражение = |(?‹! |\\p{Punct})(?=\\p{Punct})|(?‹=\\p{Punct})(?!\\p{Punct}); for(String word: string.split(regex)){ System.out.println(word); } } с этим кодом я не могу хранить две последние эмоциональные записи. - person reigeki; 17.05.2013
comment
@reigeki Да, я забыл, что смайлики могут состоять из AZ или 0-9. Обратите внимание, что было бы практически невозможно провести различие между чем-то вроде :D и ,I. Каким бы способом вы ни решили эту проблему, вам, вероятно, придется очень много проверять особые случаи. Также есть некоторая двусмысленность - Apple :-.:Dear может быть Apple,:-,.,:,Dear или Apple,:-.,:D,ear. И если правильная заглавная буква и слова, являющиеся словарными словами, не требуются, это, вероятно, просто превратилось в довольно большой проект (если вы хотите сделать это правильно, в противном случае просто используйте список всех смайликов). - person Bernhard Barker; 17.05.2013
comment
как я использую список смайлов? - person reigeki; 17.05.2013
comment
@reigeki Разделить, как я и предложил, а затем выполнить цикл и объединить строки, если комбинация существует в списке смайликов. Возможно, вам придется объединить более двух списков (например, 8-0) и проверить длину, чтобы не выполнять бессмысленную работу по проверке длинных строк. Хотя это может быть недостаточно общим, поскольку может быть . до или после (но не внутри) смайлика. В этом случае вам, вероятно, придется разделить каждый знак препинания и объединить оттуда (или вы можете попробовать разделить недопустимые символы в первом подходе). В любом случае, что-то вроде :Day, вероятно, все еще будет проблемой. - person Bernhard Barker; 17.05.2013
comment
@reigeki Другой вариант - вручную выполнить весь синтаксический анализ (пошагово пройтись по символу строки, проверить, соответствует ли то, что у вас есть до сих пор, какому-либо шаблону (шаблонам) и разорвать эту часть, если это так), но это немного больше Работа. - person Bernhard Barker; 17.05.2013

В идеале я бы предложил использовать регулярное выражение, но вам нужно будет применить сложный шаблон регулярного выражения, если вы действительно хотите использовать как можно больше сравнений/выражений. (более 100 смайлов, которые вы можете найти каждый день).

Может быть, вы можете сохранить возможные выражения/смайлики в ArrayList как String , а затем выполнить поиск с элементами arrayList в данной строке, чтобы найти выражение, а затем добавить новую строку. Например:

          //initialisation - can be done once on startup/value can be fetch from db
        ArrayList<String> list = new ArrayList<String>() ;
    list.add(":)");
    list.add("!");
    list.add("?");

    // When ever you want to parse the String
    String input=" Hello :) How are you ? I am :) not fine! ha ha!";
    System.out.println(input);
    for(String exp:list){
        input = input.replace(exp, "\n"+exp+"\n");
    }
    System.out.println(input);
person Satheesh Cheveri    schedule 17.05.2013

Что вы можете сделать, так это сохранить все обозначения эмоций в массиве. Вам нужно будет экранировать специальные символы, чтобы избежать регулярных выражений при выполнении replaceAll. После этого прокрутите все эмоции и добавьте ПРОБЕЛ перед эмоцией, где бы она ни присутствовала в предложении.

Это поможет вам позже разделить предложение по ПРОБЕЛУ. Кроме того, вы можете удалить любой двойной ПРОБЕЛ, который мог появиться.

См. код ниже (не тестировался, могут быть грамматические ошибки)

private static final String SPACE =" ";
String[]  emotionList = new String[]{':P',':)','!',....};//you might need to handle :) as :\\) to escape regex 

public void parsing(){
   for(String s:emotionList){ //add space before each emotion.
      sentence=sentence.replaceAll(s,SPACE+s);
   }

   sentence=sentence.replaceAll(SPACE+SPACE, SPACE);//optional - replace double SPACE by single SPACE.
   mywords = Arrays.asList(sentence.split(SPACE));
}
person Kshitij    schedule 17.05.2013