Pregunta

Estoy escribiendo un programa de libs locas por diversión y para programar algo. El programa en sí es bastante sencillo, pero me encuentro recurriendo a varias concatenaciones debido a la naturaleza del juego donde colocas las palabras dadas por el usuario en una oración. ¿Existe una solución elegante para recurrir a menos concatenaciones o incluso eliminarlas por algo más eficiente? Sé que al final no habrá diferencia si uso concatenaciones o no, pero tengo curiosidad por saber si hay una forma más elegante de escribir este programa.

Actualización: estoy usando Java, pero si hay una solución general para escapar de la concatenación, eso también sería apreciado.

¿Fue útil?

Solución

Una solución podría ser escribir todo su archivo de libs locas y poner tokens especiales que deben ser reemplazados por las palabras que se elijan.

  

Acaba de comprar un nuevo $ {NOUN1},   y va a $ {VERB1} usted.

Entonces puede usar, por ejemplo: String.replace (" $ {NOUN1} " ;, noun1) para todas las palabras.

Otros consejos

¿Qué idioma estás usando?

La mayoría de los idiomas de alto nivel tendrán algo similar a:

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

Hay dos formas en que puedo verte evitando por completo la concatenación en tu juego:

  1. Almacene la plantilla de la historia como una colección de tokens: partes inmutables y marcadores de posición de palabras. Luego recorra la colección generando partes inmutables y palabras de usuario en lugar de marcadores de posición de palabras.

  2. Escriba una clase de impresión personalizada que recorra la cadena de plantilla usando charAt y palabras de salida en lugar de marcadores de posición de palabras.

En lugar de llamar a String.replace para cada palabra o anexar constantemente a un StringBuilder, puede poner las palabras en una matriz ordenada y usar String.format (en jdk 1.5 o posterior) o MessageFormat.format en jdk 1.4. Lamentablemente, los formatos de patrón para los dos son diferentes.

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

o

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

Aquí hay un programa completo que completa la cadena con valores de la línea de comando.

public class Format
{
    public static void main( String[] args )
    {
        String pattern = "My %s eats your %s";
        System.out.println( String.format( pattern, (Object[])args ));
    }
}

Hay dos aspectos de su pregunta.

Primero, es posible que desee evitar el uso de concatenaciones directamente en su código. Luego puede usar alguna rutina de formateo de cadenas desde el tiempo de ejecución. Esto no omitirá las concatenaciones, pero las moverá de su código al tiempo de ejecución.

Segundo, es posible que desee realizar concatenaciones de manera más eficiente. Esa es otra historia. Lo más importante aquí es preasignar el búfer lo suficientemente grande para la cadena concatenada, ya que las reasignaciones de memoria son bastante caras. Copiar subcadenas en las cadenas de resultados suele ser menos costoso y un mal necesario.

No se me ocurre nada en términos de una forma general de evitar la concatenación. Lo que podría hacer es escribir usted mismo algún tipo de clase auxiliar que simplifique el trabajo de concatenación para usted. Sin embargo, una sugerencia que me gustaría darle es no concatenar cadenas directamente como

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

La implementación de la concatenación de cadenas es bastante lenta en Java, por lo que es una mejor práctica usar StringBuffer, especialmente si haces muchas concatenaciones:

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

Algo como esto. No comprobé esto ahora en un compilador, pero estoy seguro de que puedes resolverlo tú mismo.

No estoy seguro acerca de Java, pero en algunos otros lenguajes, como PHP y Javascript, crear una matriz y unir todos sus elementos puede ser más rápido.

Ejemplo de Javascript:

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

Ejemplo de PHP:

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

Este método es mejor si desea poner un delimitador entre cada cadena, en cuyo caso no solo será más rápido sino más compacto y legible.

Al "evitar la concatenación" supongo que te refieres a asignar el espacio para la nueva cadena y asignarla. Si está en .NET, entonces un StringBuilder debería ayudar a algunos, creo.

Si tiene un String y necesita modificarlo con mucha frecuencia, usar una matriz char [] y crear un String cuando termine de modificarlo podría ser el truco.

Sin duda es posible hacer esto sin concatenación si lo desea. Aunque probablemente no valga mucho la pena.

Depende en parte de dónde va a mostrar el resultado. Si está en la web o en la consola, puede escribir el resultado directamente en una secuencia de salida.

Entonces, por ejemplo, si su plantilla era algo así como " el% 001 saltó del% 002 " usted podría:

1) escanee la cadena para encontrar dónde están las variables. 2) divida la cadena en una lista de componentes " los ", " saltados fuera de " ;, en este caso 3) recorra los elementos de su lista y los resultados y vuélvalos a la salida con algo como esto:

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

Ahora. No sé si llamarías eso 'elegante' o no. Probablemente sería un poco rápido. Como dije, tal vez sea apropiado si se trata de un servicio web y se hizo muy popular, etc.

Si se trata de una aplicación GUI, podría escribir código para dibujar las cadenas por separado, pero eso probablemente tomaría más tiempo que la concatenación.

pero una cosa que podría hacer es usar un ByteArrayOutputStream y preasignar suficiente espacio para que pueda contener el madlib lleno sin realizar asignaciones adicionales. Eso también sería bastante rápido.

¿Por qué quieres evitar la concatenación si es por limpieza? Intenta alinearla bien y puede terminar viéndose sorprendentemente bien. Incluso si estás preocupado por el rendimiento, es posible que no necesites usar el generador de cadenas, creo que si lo haces un montón de concatenaciones simplemente (es decir, "fdsfsd" + var1 + var2 + "dsfsdf" + + "tyhty" se compila en lo mismo que el generador de cadenas (efectivamente el mismo y se ve más limpio). El generador de cadenas tiene sentido si usted están concatenando un montón de cosas en un bucle o con un flujo complejo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top