Как реализовать коллекцию (список, карту?) Сложных строк в Java? - PullRequest
4 голосов
/ 23 апреля 2010

Проблема - у меня есть что-то вроде следующих записей, 1000 из них:

args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
args1=msg args2=flow args3=content args4=depth args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=content args6=within ==> args5=content
args1=msg args2=flow args3=content args6=within args7=distance ==> args5=content
args1=msg args2=flow args3=flow ==> args4=flowbits
args1=msg args2=flow args3=flow args5=content ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args4=flowbits
args1=msg args2=flow args3=flow args6=depth ==> args5=content
args1=msg args2=flow args4=depth ==> args3=content
args1=msg args2=flow args4=depth args5=content ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within ==> args3=content
args1=msg args2=flow args4=depth args5=content args6=within args7=distance ==> args3=content

Я делаю какой-то метод предложения.Скажем, args1 = msg args2 = поток args3 = поток ==> args4 = flowbits

Если предложение содержит msg, поток и другой поток, то я должен вернуть предложение потоковых бит.

Как я могу это делать?Я знаю, что должен сканировать (всякий раз, когда символ нажимается в текстовой области) список или массив для совпадения и возвращать результат, но 1000 записей, как мне его реализовать?

Я думаю о HashMap, но могу ли я сделать что-то вроде этого?

<"msg, flow, flow", "flowbits">

Кроме того, в предложении аргументы могут быть не в порядке, поэтому при условии, чтоэто поток, поток, сообщение, тогда я не могу ничего сопоставить в HashMap, поскольку ключ «msg, поток, поток».

Что мне делать в этом случае?Пожалуйста помоги.Спасибо миллион!

Ответы [ 6 ]

4 голосов
/ 23 апреля 2010

Ключ Map может быть другим Map или Set. Похоже, все, что вам нужно, это что-то вроде Map<Set<String>, String> или, возможно, Map<Map<String, String>, Map.Entry<String, String>> - не уверен, где эти "args1", "args2" имеют отношение.

1 голос
/ 23 апреля 2010

Другими словами, старайтесь не выполнять всю логику в вашем парсере.Разделите логику, чтобы синтаксический анализатор просто обнаруживал структуру, а затем строил объекты, чтобы помочь вам обеспечить соблюдение правил.Синтаксический анализатор может легко обнаружить аргументы и использовать их для создания списка.

Если вы создаете класс, содержащий ваши аргументы, например:

public class Arg {
    public int number;
    public String value;

    public Arg(int num, String val) {
        this.number = num;
        this.value = val;
    }

    @Override
    public String toString()
    {
   return "[Arg num=" + number + ", value=" + value + "]";
    }

}

, то вы можете поместить их в простоеХеш-таблица.

Map<Arg> argList = new HashMap<Arg>();

Затем вы можете сделать логику, используя, может быть, счетчик и содержит () или indexOf () и т. Д.

Наличие класса Arg также упрощает сортировку.Если вам нужен список, отсортированный по позиции аргумента, вы создаете для этого компаратор.

import java.util.Comparator;

public class ArgNumComparator implements Comparator<Arg> {
    public int compare(Arg o1, Arg o2) {
       if (o1.number == o2.number) {
        return 0;
       }
       return o1.number < o2.number ? -1 : 1 ;
   }    
}

Сортировка по значению аргумента еще проще, поскольку вы можете повторно использовать сравниваемое () значение Strings.

import java.util.Comparator;

public class ArgValComparator implements Comparator<Arg>
{
    public int compare(Arg o1, Arg o2)
   {
       return o1.value.compareTo(o2.value);
   }
}

Затем, чтобы выполнить сортировку, используйте Collections.sort () примерно так:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArgList{
    public static void main(String[] args)  {
        //args1=msg args2=flow args3=content args4=depth args6=within ==> args5=content
        List<Arg> l = new ArrayList<Arg>();  
        // hard-coded example instead of more likely parsing
        l.add(new Arg(1, "msg"));
        l.add(new Arg(2, "flow"));
        l.add(new Arg(3, "content"));
        l.add(new Arg(4, "depth"));
        l.add(new Arg(5, "flow"));
        l.add(new Arg(6, "within"));

    Collections.sort(l, new ArgValComparator()); // take your pick of comparators

    System.out.println(l); // uses the toString() of Arg.
    }
}

EDIT: добавлен метод toString () в Arg и изменен список вПример с двумя аргументами «потока».

Запуск с новым кодом toString выводит на консоль следующее:

[[Arg num = 3, value = content], [Arg num = 4, значение = глубина], [Arg num = 2, значение = поток], [Arg num = 5, значение = поток], [Arg num = 1, значение = msg], [Arg num = 6, значение= в пределах]]

Как видите, два аргумента со значением = "поток" теперь рядом друг с другом.Чтобы обнаружить несколько аргументов, где значение = «поток», можно сделать так:

boolean flowFound = false;
for (Arg arg : l){
   if (arg.value.compareToIgnoreCase("flow") == 0) {
      if (flowFound)  //already found one? {
         // action when second "flow" exists
         System.out.println("2nd flow found");
      }
      else {
         flowFound = true;  // found the first "flow"
      }
   }          
}
0 голосов
/ 23 апреля 2010

Поскольку порядок появления строк не имеет значения, вы можете расположить их в алфавитном порядке при создании ключа.Предположим, что вам нужно то же предложение для, msg, flow, flow и flow, msg, flow and flow, flow, msg - в алфавитном порядке, это «поток, flow, msg», так что именно это вы используете в качестве ключа.

0 голосов
/ 23 апреля 2010

Вы можете создать объект и инкапсулировать в нем логику для каждой строки. Если ввод в точности соответствует описанию, вы должны быть в состоянии извлечь аргументы с помощью простого регулярного выражения и групп захвата, а затем вызвать сеттеры для вашего объекта для каждого аргумента. Тогда ваша структура данных будет просто списком этих объектов.

0 голосов
/ 23 апреля 2010

На первый взгляд, это похоже на хорошее использование синтаксического анализатора и формальной грамматики, а не коллекции. ANTLR - это популярный генератор синтаксического анализа для Java.

Если синтаксический анализатор не решит вашу проблему, если аргументы могут появляться в любом порядке.В этой ситуации я использовал бы некоторый объект Case, который сочетает в себе правила и действия, и использовал бы простой Map<String,List<Case>>, чтобы найти экземпляры, которые могут применяться к данному тексту (вы извлекли бы отдельные слова из текста, чтобы исследоватьи может комбинировать списки, возвращаемые каждым зондом).

У меня нет времени, чтобы привести полный пример, но объект Case, вероятно, будет выглядеть примерно так:

public interface Case {
    boolean evaluate(String text);
    String result();
}
0 голосов
/ 23 апреля 2010

да, вы можете сделать <"msg, flow, flow", "flowbits"> в хэш-карте.Это лучшее решение, я не знаю.

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