Domanda

Sto scrivendo un programma libs pazzo per divertimento e per programmare semplicemente qualcosa. Il programma in sé è piuttosto semplice, ma mi ritrovo a ricorrere a diverse concatenazioni a causa della natura del gioco in cui inserisci le parole fornite dall'utente in una frase. Esiste un modo elegante per ricorrere a meno concatenazioni o addirittura eliminarle per qualcosa di più efficiente? So che alla fine non farà alcuna differenza se uso concatenazioni o no, ma sono curioso di sapere se esiste un modo più elegante di scrivere questo programma.

Aggiornamento: sto usando Java, ma se ci fosse una soluzione generale per sfuggire alla concatenazione, anche questo sarebbe apprezzato.

È stato utile?

Soluzione

Una soluzione potrebbe essere quella di scrivere l'intero file libs pazzo e inserire token speciali che devono essere sostituiti dalle parole scelte.

  

Hai appena acquistato un nuovissimo $ {NOUN1},   e ti farà $ {VERB1}.

Quindi puoi usare ad esempio: String.replace (" $ {NOUN1} " ;, sostantivo1) per tutte le parole.

Altri suggerimenti

Quale lingua stai usando?

La maggior parte delle lingue di alto livello avrà qualcosa di simile a:

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

Ci sono due modi in cui posso vederti evitare completamente la concatenazione nel tuo gioco:

  1. Archivia il modello della storia come una raccolta di token: parti immutabili e segnaposto di parole. Quindi scorrere la raccolta producendo parti immutabili e parole utente anziché parole segnaposto.

  2. Scrivi una classe di stampa personalizzata che eseguirà il ciclo attraverso la stringa del modello usando charAt e le parole di output anziché i segnaposto di parole.

Anziché chiamare String.replace per ogni parola o accodare costantemente a StringBuilder, è possibile inserire le parole in un array ordinato e utilizzare String.format (in jdk 1.5 o versioni successive) o MessageFormat.format in jdk 1.4. Sfortunatamente i formati dei pattern per i due sono diversi.

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 );

Ecco un programma completo che riempie la stringa con i valori della riga di 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 ));
    }
}

Ci sono due aspetti della tua domanda.

Innanzitutto, potresti voler evitare di usare le concatenazioni direttamente nel tuo codice. Quindi è possibile utilizzare alcune routine di formattazione delle stringhe dal runtime. Questo non salterà le concatenazioni, ma le sposterà dal tuo codice al runtime.

In secondo luogo, potresti voler concatenare in modo più efficace. Questa è un'altra storia. La cosa più importante qui è preallocare il buffer abbastanza grande per la stringa concatenata, poiché le riallocazioni di memoria sono piuttosto costose. Copiare sottostringhe nelle stringhe dei risultati è generalmente meno costoso e rappresenta un male necessario.

Nulla mi viene in mente in termini di un modo generale per evitare la concatenazione. Quello che potresti fare è scrivere una sorta di classe di aiuto che semplifichi il lavoro di concatenazione per te. Un suggerimento che vorrei darti, tuttavia, è di non concatenare direttamente le stringhe come

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

L'implementazione della concatenazione di stringhe è piuttosto lenta in Java, quindi è meglio usare StringBuffer, specialmente se si fanno molte concatenazioni:

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

Qualcosa del genere. Non l'ho verificato ora in un compilatore, ma sono sicuro che puoi capirlo da solo.

Non sono sicuro di Java ma in alcuni altri linguaggi come PHP e Javascript la creazione di un array e l'unione di tutti i suoi elementi può essere più veloce.

Esempio Javascript:

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

Esempio di PHP:

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

Questo metodo è il migliore se vuoi mettere un delimitatore tra ogni stringa, nel qual caso non solo sarà più veloce ma più compatto e leggibile.

Per "evitare la concatenazione" suppongo che intendi allocare lo spazio per la nuova stringa e assegnarlo? Se sei su .NET, un StringBuilder dovrebbe aiutare alcuni, credo.

Se si dispone di una stringa è necessario modificarla molto spesso, utilizzare una matrice char [] e creare una stringa una volta terminata la modifica potrebbe essere utile.

È certamente possibile farlo senza concatenazione se lo si desidera. Anche se probabilmente non è molto utile.

Dipende in parte da dove visualizzerai il risultato. Se si trova sul Web o sulla console, è possibile scrivere il risultato direttamente su un flusso di output.

Ad esempio, se il tuo modello era simile a "% 001 è saltato fuori da% 002 " potresti:

1) scansiona la stringa per trovare dove sono le variabili. 2) suddividere la stringa in un elenco di componenti "il", "saltato fuori dal", in questo caso 3) scorrere gli elementi del tuo elenco e i risultati e scaricarli per ottenere un risultato simile al seguente:

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

Ora. Non so se lo chiameresti "elegante" o no. Probabilmente sarebbe abbastanza veloce. Come ho detto, forse appropriato se questo era un servizio web ed è diventato molto popolare, ecc.

Se si tratta di un'app GUI, è possibile scrivere codice per disegnare le stringhe separatamente, ma ciò richiederebbe probabilmente più tempo della concatenazione.

ma una cosa che potresti è usare un ByteArrayOutputStream e pre-allocare abbastanza spazio in modo che possa contenere il madlib compilato senza fare allocazioni aggiuntive. Sarebbe anche abbastanza veloce.

Perché vuoi evitare la concatenazione se è per pulizia prova ad allinearlo bene e potrebbe sembrare sorprendentemente buono. Anche se sei preoccupato per le prestazioni potresti non aver bisogno di usare il generatore di stringhe, credo che se lo fai un sacco di concatenazioni semplicemente (cioè "fdsfsd" + var1 + var2 + "dsfsdf" + "tyhty" si compila alla stessa cosa del generatore di stringhe (effettivamente lo stesso e sembra più pulito). String Builder ha senso se tu stanno concedendo un sacco di cose in un ciclo o con un flusso complesso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top