Есть ли элегантный способ обойти конкатенацию?

StackOverflow https://stackoverflow.com/questions/649463

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

  

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

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

Другие советы

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

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

String.Format("{0} {1} {2} {3}", word1, word2, word3, word4);

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

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

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

  • Вместо того чтобы вызывать 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 ));
        }
    }
    

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

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

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

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

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

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

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

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

    Не уверен насчет 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));
    

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

    Под «избеганием конкатенации» я предполагаю, что вы имеете в виду выделение места для новой строки и ее назначение? Если вы работаете в .NET, то StringBuilder должен помочь некоторым, я думаю.

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

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

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

    Так, например, если бы ваш шаблон был чем-то вроде "%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 без дополнительных выделений.Это тоже было бы довольно быстро.

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top