Question

Je suis en train d’écrire un programme Mad Libs pour le plaisir et juste pour programmer quelque chose. Le programme lui-même est assez simple, mais je suis amené à recourir à plusieurs concaténations en raison de la nature du jeu où vous placez les mots donnés par l'utilisateur dans une phrase. Existe-t-il un moyen élégant de recourir à moins de concaténations ou même de les éliminer pour obtenir quelque chose de plus efficace? Je sais qu'en fin de compte, si j'utilise des concaténations ou non, cela ne fera aucune différence, mais je suis curieux de savoir s'il existe un moyen plus élégant d'écrire ce programme.

Mise à jour: j'utilise Java, mais s'il existe une solution générale pour échapper à la concaténation, nous l'apprécierions également.

Était-ce utile?

La solution

Une solution pourrait être d'écrire tout votre fichier mad lib et de placer des jetons spéciaux devant être remplacés par les mots choisis.

  

Vous venez d'acheter un tout nouveau {NOUN1} $,   et il va vous $ {VERB1}.

Vous pouvez ensuite utiliser, par exemple: String.replace ("$ {NOUN1}", noun1) pour tous les mots.

Autres conseils

Quelle langue utilisez-vous?

La plupart des langages de haut niveau auront quelque chose de similaire à:

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

Je peux vous voir de deux manières différentes en évitant la concaténation dans votre jeu:

  1. Stockez le modèle d’histoire en tant que collection de jetons: parties immuables et espaces réservés pour les mots. Parcourez ensuite la collection en affichant des parties immuables et des mots utilisateur au lieu d'espaces réservés pour les mots.

  2. Écrire une classe d'impression personnalisée qui parcourra la chaîne de modèle en utilisant charAt et des mots en sortie à la place des espaces réservés aux mots.

Plutôt que d’appeler String.replace pour chaque mot ou d’ajouter constamment à StringBuilder, vous pouvez placer les mots dans un tableau ordonné et utiliser String.format (dans jdk 1.5 ou plus récent) ou MessageFormat.format dans jdk 1.4. Malheureusement, les formats de motif pour les deux sont différents.

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

ou

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

Voici un programme complet qui remplit la chaîne avec les valeurs de la ligne de commande.

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

Il y a deux aspects de votre question.

Tout d'abord, vous pouvez éviter d'utiliser des concaténations directement dans votre code. Vous pouvez ensuite utiliser une routine de formatage de chaîne à partir du runtime. Cela ne sautera pas les concaténations, mais les déplacera de votre code à l'exécution.

Deuxièmement, vous souhaiterez peut-être effectuer des concaténations plus efficacement. C'est une autre histoire. La chose la plus importante ici est de préallouer le tampon suffisamment grand pour la chaîne concaténée, car les réaffectations de mémoire sont assez coûteuses. Copier des sous-chaînes dans les chaînes de résultats est généralement moins coûteux et constitue un mal nécessaire.

Rien ne me vient à l’esprit comme moyen général d’éviter la concaténation. Ce que vous pouvez faire est d’écrire vous-même une sorte de classe d’assistance qui simplifie le travail de concaténation pour vous. Une suggestion que je voudrais cependant vous faire est de ne pas concaténer directement les chaînes comme

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

L'implémentation de la concaténation de chaînes est assez lente en Java. Il est donc préférable d'utiliser StringBuffer, en particulier si vous effectuez de nombreuses concaténations:

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

Quelque chose comme ça. Je n'ai pas vérifié cela maintenant dans un compilateur, mais je suis sûr que vous pouvez le découvrir vous-même.

Pas sûr de Java, mais dans d'autres langages tels que PHP et Javascript, créer un tableau et joindre tous ses éléments peut être plus rapide.

Exemple Javascript:

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

Exemple PHP:

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

Cette méthode est préférable si vous souhaitez insérer un délimiteur entre chaque chaîne. Dans ce cas, il sera non seulement plus rapide, mais plus compact et lisible.

Par "éviter la concaténation", je suppose que vous voulez dire allouer de l’espace à la nouvelle chaîne et l’affecter? Si vous êtes sur .NET, alors un StringBuilder devrait aider certains, je pense.

Si vous avez besoin d'une chaîne, vous devez la modifier très souvent. L'utilisation d'un tableau char [] et la création d'une chaîne lorsque vous le modifiez peuvent faire l'affaire.

Il est certainement possible de le faire sans concaténation si vous le souhaitez. Bien que ce ne soit probablement pas très utile.

Cela dépend en partie de l'endroit où vous allez afficher le résultat. Si c'est sur le Web ou la console, vous pouvez écrire le résultat directement dans un flux de sortie.

Ainsi, par exemple, si votre modèle ressemblait à "" le% 001 est sorti du% 002". vous pourriez:

1) balayez la chaîne pour localiser les variables. 2) diviser la chaîne en une liste de composants "le", "sauté hors du", dans ce cas 3) parcourez les éléments de votre liste et les résultats, puis exportez-les avec un résultat similaire à celui-ci:

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

Maintenant. Je ne sais pas si vous qualifieriez cela d'élégant ou non. Ce serait probablement rapide. Comme je l'ai dit, cela pourrait être approprié s'il s'agissait d'un service Web devenu super populaire, etc.

S'il s'agit d'une application graphique, vous pouvez écrire du code pour dessiner les chaînes séparément, mais cela prendrait probablement plus de temps que la concaténation.

mais vous pouviez utiliser un ByteArrayOutputStream et pré-allouer suffisamment d’espace pour qu’il puisse contenir la bibliothèque remplie sans effectuer d’allocations supplémentaires. Ce serait assez rapide aussi.

Pourquoi voulez-vous éviter la concaténation si c'est pour la propreté, essayez de l'aligner correctement et cela peut finir par paraître étonnamment bon.Même si vous êtes inquiet pour la performance, vous n'aurez peut-être pas besoin d'utiliser un constructeur de cordes, un tas de concaténations simplement (c'est-à-dire "fdsfsd" + var1 + var2 + "dsfsdf" + "tyhty", il se compile de la même manière que le constructeur de chaînes (en fait, le même et semble plus propre). String Builder a un sens si vous concassent une tonne de choses dans une boucle ou avec un flux complexe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top