Нужно связать строки с целыми числами более чистым / более эффективным способом - PullRequest
2 голосов
/ 18 апреля 2011

Как я могу улучшить это?

Отношение один к одному и непрерывное на [-1,5], поэтому я думал об использовании enum, но я не уверен, как сравнить строковое значение со значением enum.

Если есть лучший способ сделать это, пожалуйста, предложите.

Спасибо!

private int evaluateWord(String sval) {
    if (sval.equals("program"))
        return 1;
    else if (sval.equals("begin"))
        return 2;
    else if (sval.equals("end"))
        return 3;
    else if (sval.equals("int"))
        return 4;
    else if (sval.equals("if"))
        return 5;
    else
        System.exit(0);

Ответы [ 8 ]

4 голосов
/ 18 апреля 2011

Рассматривали ли вы один раз вставить отображение в HashMap, а затем просто запросить карту?

Например, что-то вроде этого:

 private static final Map<String,Integer> m_map = new HashMap<String,Integer>();
 static {
     m_map.put( "program", 1 );
     m_map.put( "begin", 2 );
     m_map.put( "end", 3 );
     m_map.put( "int", 4 );
     m_map.put( "if", 5 );
 }

 private int evaluateWord(String sval) {
     Integer value = m_map.get( sval );
     if ( null != value ) {
        return value;
     }
     else {
        System.exit(0);
     }
 }

Кстати, похоже, что вы пишете парсер. Разумно написать парсер вручную. Другой вариант, если у вас нет веских причин писать его вручную, это генератор синтаксических анализаторов, такой как ANTLR .

4 голосов
/ 18 апреля 2011

Использование перечисления:

enum Word {
  PROGRAM(1,"program"),
  BEGIN(2,"begin"),
  END(3,"end"),
  INT(4,"int"),
  IF(5,"if");

  private final int value;
  private final String representation;

  Word(int value, String representation)
  {
    this.value = value;
    this.representation = representation;
  }

  public int value()
  { return value; }

  private static Map<String, Word> fromRep =
    new HashMap<String, EnumExample2.Word>();

  public static Word fromRepresentation(String rep) {
    if (!validRep(rep)) {
      throw new IllegalArgumentException("No rep: "+rep);
    }

    return fromRep.get(rep);
  }

  public static boolean validRep(String rep)
  { return fromRep.get(rep) != null; }

  static {
    for (Word word : Word.values()) {
      fromRep.put(word.representation, word);
    }
  }
}

Тогда ваша логика:

private int evaluateWord(String sval) {
  if (!Word.validRep(sval)) {
    System.exit(0);
  }

  return Word.fromRepresentation(sval).value();
}
2 голосов
/ 18 апреля 2011

Для этого и нужна карта;

Создайте HashMap, добавьте ключ и значения к карте, например

wordMap.put("program", Integer.valueOf(1));

....

, затемчтобы получить значение сделайте

Integer val = wordMap.get(sval);
2 голосов
/ 18 апреля 2011

Может работать хэш-карта:

private static HashMap<String, Integer> lookup = new HashMap<String, Integer>();
static {
    lookup.put("program", 1);
    lookup.put("being", 2);
    lookup.put("end", 3);
    lookup.put("int", 4);
    lookup.put("if", 5);
}

private int evaluateWord(String sval) {
    if ( lookup.containsKey(sval) ) {
        return lookup.get(sval);
    }
    System.exit(0); 
}
0 голосов
/ 18 апреля 2011

Вы можете просто использовать массив или хэш-карту для сопоставления значений перечисления со строковыми значениями.

0 голосов
/ 18 апреля 2011

Вдохновленный вашим комментарием к перечислению, я представляю следующее.Это немного глупо, но:

enum Word
{
    PROGRAM (1), BEGIN (2), END (3), INT (4), IF (5);

    public int value;

    public Word (int value)
    {
        this.value = value;
    }
};

int evaluateWord (String word)
{
    return Word.valueOf(word.toUpperCase( )).value;
}

Я люблю перечисления Java, потому что вы можете делать такие вещи.Это особенно полезно, если позже вы захотите (например) добавить уникальное поведение для каждого слова или вести длинный список слов.Обратите внимание, что регистр не учитывается.

Или, альтернативно:

enum Word
{
    PROGRAM, BEGIN, END, INT, IF;
};

int evaluateWord (String word)
{
    return Word.valueOf(word.toUpperCase( )).ordinal( ) + 1;
}
0 голосов
/ 18 апреля 2011

Зачем вам нужен (очень субъективный) "более чистый" способ?

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

Одна вещь, которую вы, возможно, захотите сделать для лучшего вида кода (еслиэто важно), чтобы отбросить else бит, они совершенно не нужны:

private int evaluateWord(String sval) {
    if (sval.equals("program")) return 1;
    if (sval.equals("begin"))   return 2;
    if (sval.equals("end"))     return 3;
    if (sval.equals("int"))     return 4;
    if (sval.equals("if"))      return 5;
    System.exit(0);
}
0 голосов
/ 18 апреля 2011

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

Используйте хеш-таблицу и просто вставьте пары. Таким образом, все ваши вызовы valuWord будут возвращаться в амортизированном постоянном времени. :)

Удачи!

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