Есть ли элегантная работа вокруг объединения? - PullRequest
3 голосов
/ 16 марта 2009

Я пишу безумную программу libs для развлечения и просто для программирования чего-либо. Сама программа довольно проста, но я обнаружил, что прибегаю к нескольким объединениям из-за характера игры, в которой вы помещаете заданные пользователем слова в предложение. Есть ли элегантная работа, чтобы прибегнуть к меньшему количеству конкатенаций или даже устранить их для чего-то более эффективного? Я знаю, в конце концов, не будет никакой разницы, буду я использовать конкатенации или нет, но мне любопытно, есть ли более элегантный способ написания этой программы.

Обновление: я использую java, но если есть общее решение для избежания конкатенации, это также приветствуется.

Ответы [ 11 ]

8 голосов
/ 16 марта 2009

Одним из решений может быть выписать весь файл сумасшедших библиотек и добавить специальные токены, которые должны быть заменены выбранными словами.

Вы только что купили новый $ {NOUN1}, и он собирается $ {VERB1} вам.

Тогда вы можете использовать, например: String.replace("${NOUN1}", noun1) для всех слов.

3 голосов
/ 16 марта 2009

Какой язык вы используете?

У большинства языков высокого уровня будет что-то похожее на:

String.Format("{0} {1} {2} {3}", word1, word2, word3, word4);
2 голосов
/ 17 марта 2009

Вместо вызова String.replace для каждого слова или постоянного добавления в StringBuilder вы можете поместить слова в упорядоченный массив и использовать String.format (в jdk 1.5 или новее) или MessageFormat.format в jdk 1.4. К сожалению, форматы шаблонов для них разные.

String myPattern = "My %s eats your %s";
// get values from the user here
String result = String.format( myPattern, (Object[])myArray );

или

String myPattern = "My {0} eats your {1}";
// get values from the user here
String result = MessageFormat.format( myPattern, (Object[])myArray );

Вот полная программа, которая заполняет строку значениями из командной строки.

public class Format
{
    public static void main( String[] args )
    {
        String pattern = "My %s eats your %s";
        System.out.println( String.format( pattern, (Object[])args ));
    }
}
2 голосов
/ 16 марта 2009

Я вижу, как вы полностью избегаете объединения в своей игре двумя способами:

  1. Сохраните шаблон истории как коллекцию токенов: неизменяемые части и заполнители слов. Затем переберите коллекцию, выводя неизменяемые части и пользовательские слова вместо заполнителей слов.

  2. Напишите пользовательский класс печати, который будет циклически проходить по строке шаблона, используя charAt и выводя слова вместо заполнителей слов.

1 голос
/ 16 марта 2009

Не уверен насчет Java, но в некоторых других языках, таких как PHP и Javascript, создание массива и объединение всех его элементов может быть быстрее.

Пример Javascript:

var str = str1 + str2 + str3 + "str4" + str5 + "str6" + str7;
var str = [str1, str2, str3, "str4", str5, "str6", str7].join("");

Пример PHP:

$str = $str1 . $str2 . $str3 . "str4" . $str5 . "str6" . $str7;
$str = implode("", array($str1, $str2, $str3, "str4", $str5, "str6", $str7));

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

1 голос
/ 16 марта 2009

Ничто не приходит мне на ум с точки зрения общего способа избежать конкатенации. Что вы могли бы сделать, так это написать себе некоторый вспомогательный класс, который упростит вам задачу конкатенации. Однако я хотел бы дать вам совет не объединять строки как

.
String x = "Hi";
String y = x + " there!";

Реализация конкатенации строк в Java довольно медленная, поэтому лучше использовать вместо нее StringBuffer, особенно если вы выполняете много конкатенаций:

StringBuffer myStringBuffer = new StringBuffer();
myStringBuffer.append("Hi");
myStringBuffer.append(" there!");

Как то так. Я не проверял это сейчас в компиляторе, но я уверен, что вы можете понять это сами.

1 голос
/ 16 марта 2009

Есть два аспекта вашего вопроса.

Во-первых, вы можете не использовать конкатенации непосредственно в своем коде. Затем вы можете использовать некоторую подпрограмму форматирования строки из среды выполнения. Это не пропустит конкатенации, но переместит их из вашего кода во время выполнения.

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

0 голосов
/ 16 февраля 2010

Почему вы хотите избежать конкатенации, если для чистоты попробуйте аккуратно выстроить ее, и она может в конечном итоге выглядеть на удивление хорошо. Даже если вы беспокоитесь о производительности, вам может не понадобиться использовать построитель строк, я считаю, что если вы это сделаете просто несколько конкатенаций (т. е. "fdsfsd" + var1 + var2 + "dsfsdf" + "tyhty") он компилируется в то же самое, что и построитель строк (фактически, тот же и выглядит чище). String Builder имеет смысл, если вы объединяете тонна вещей в петле или со сложным потоком.

0 голосов
/ 16 февраля 2010

Конечно, можно сделать это без конкатенации, если хотите. Хотя, наверное, не очень стоит.

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

Так, например, если ваш шаблон был что-то вроде "% 001 выпрыгнул из% 002", вы могли бы:

1) просканируйте строку, чтобы найти переменные. 2) разбить строку на список компонентов «the», «выпрыгнул из», в данном случае 3) перебрать элементы вашего списка и результаты и вывести их на вывод примерно так:

PrintStream  = //get output from somewhere
for(int i = 0; i < pieces.size()-1 ; i++){
   ps.print(peices.get(i));
   ps.print(answers.get(i));
}
ps.print(pieces.get(pieces.size()-1));//last one

Теперь. Я не знаю, назовешь ли ты это "элегантно" или нет. Вероятно, это будет довольно быстро. Как я уже сказал, может быть уместно, если это был веб-сервис, который стал очень популярным и т. Д.

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

но одна вещь, которую вы могли бы сделать, это использовать ByteArrayOutputStream и предварительно выделить достаточно места, чтобы он мог содержать заполненный madlib без дополнительных выделений. Это было бы довольно быстро.

0 голосов
/ 16 февраля 2010

Если у вас есть String, вам нужно очень часто его модифицировать, используя массив char [] и создав String, когда вы закончите его модификацию. Это может помочь.

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