2010-04-28 25 views
5

const 
states : array [0..49,0..1] of string = 
(
('Alabama','AL'), 
('Montana','MT'), 
('Alaska','AK'), 
('Nebraska','NE'), 
('Arizona','AZ'), 
('Nevada','NV'), 
('Arkansas','AR'), 
('New Hampshire','NH'), 
('California','CA'), 
('New Jersey','NJ'), 
('Colorado','CO'), 
('New Mexico','NM'), 
('Connecticut','CT'), 
('New York','NY'), 
('Delaware','DE'), 
('North Carolina','NC'), 
('Florida','FL'), 
('North Dakota','ND'), 
('Georgia','GA'), 
('Ohio','OH'), 
('Hawaii','HI'), 
('Oklahoma','OK'), 
('Idaho','ID'), 
('Oregon','OR'), 
('Illinois','IL'), 
('Pennsylvania','PA'), 
('Indiana','IN'), 
('Rhode Island','RI'), 
('Iowa','IA'), 
('South Carolin','SC'), 
('Kansas','KS'), 
('South Dakota','SD'), 
('Kentucky','KY'), 
('Tennessee','TN'), 
('Louisiana','LA'), 
('Texas','TX'), 
('Maine','ME'), 
('Utah','UT'), 
('Maryland','MD'), 
('Vermont','VT'), 
('Massachusetts','MA'), 
('Virginia','VA'), 
('Michigan','MI'), 
('Washington','WA'), 
('Minnesota','MN'), 
('West Virginia','WV'), 
('Mississippi','MS'), 
('Wisconsin','WI'), 
('Missouri','MO'), 
('Wyoming','WY') 
); 
function getabb(state:string):string; 
var 
    I:integer; 
begin 
    for I := 0 to length(states) -1 do 
    if lowercase(state) = lowercase(states[I,0]) then 
    begin 
    result:= states[I,1]; 
    end; 
end; 
function getstate(state:string):string; 
var 
    I:integer; 
begin 
    for I := 0 to length(states) -1 do 
    if lowercase(state) = lowercase(states[I,1]) then 
    begin 
    result:= states[I,0]; 
    end; 
end; 
procedure TForm2.Button1Click(Sender: TObject); 
begin 
edit1.Text:=getabb(edit1.Text); 
end; 

procedure TForm2.Button2Click(Sender: TObject); 
begin 
edit1.Text:=getstate(edit1.Text); 
end; 

end. 

C'è un modo bette per fare questo?Delphi - C'è un modo migliore per ottenere abbreviazioni di stato dai nomi di stato

+0

Hai un errore di battitura: "South Carolin" dovrebbe essere "South Carolina" – dthorpe

+0

Grazie! Non l'ho visto ... – Bill

+1

Come si misura "meglio"? Più veloce? Più breve? Estensibile? Autorevole? –

risposta

7

Se si utilizza D2009 o D2010, utilizzare uno TDictionary<string, string> da Generics.Collections. Dichiara l'array di costanti come se fosse tu, quindi imposta il dizionario inserendo ogni coppia nel dizionario. Quindi usa la proprietà predefinita del dizionario per fare le tue ricerche.

+1

Suggerirei due dizionari, uno per ogni funzione. –

2

Si noti che in minuscolo (a) = in minuscolo (b) è più lento di sameText (a, b).

Inoltre, è possibile accelerare ulteriormente la procedura memorizzando le stringhe nell'array solo in minuscolo, quindi nella routine di ricerca si inizia convertendo l'input in minuscolo. Quindi puoi usare la funzione ancora più veloce sameStr (a, b). Ma ovviamente, quando viene trovata una corrispondenza, è necessario formattarla capitalizzando le lettere iniziali. Questo approccio di accelerazione non è probabilmente molto importante per una lista così piccola di stringhe. Dopo tutto, non ci sono troppi stati negli Stati Uniti.

Inoltre, si dovrebbe dichiarare le funzioni usando argomenti const, cioè scrivere

function getabb(const state:string):string; 

invece di

function getabb(state:string):string; 

(a meno che non si desidera modificare lo stato nella routine).

Infine, è possibile rendere il codice più compatto e leggibile omettendo lo begin e end dei loop for.

+1

In nessun modo è il più veloce (ed è strano che inizi dicendo che è il più veloce, e poi continua a suggerire aumenti di velocità). Una tabella hash sarà più veloce. In effetti, due tabelle hash, una per 'getabb' e una per' getstate', sviluppate dinamicamente all'avvio fino a quando non ci sono collisioni, sono ancora più veloci. Forse ancora più veloce è una struttura trie. Ma se vuoi veramente massimizzarlo, codifica direttamente i percorsi trie, che ti permettono di ottimizzare i casi limite come "Missouri" e "Mississippi". –

+0

@Marcelo: In linea di principio significa che potrebbero essere necessarie piccole modifiche, ma che l'idea principale è OK. Ma hai ragione non è il più veloce in ogni caso quindi rimuoverò quella parte errata. I primi secondi in cui ho letto la domanda ho pensato che il problema fosse semplicemente quello di ottenere l'ennesimo elemento di un array, cioè inserire un numero e ottenere una stringa. E poi non ci sarebbe alcun metodo più veloce. E in qualche modo questa conclusione è rimasta nella mia mente anche dopo aver capito il vero problema. –

8

Questo tipo di dati deve essere hardcoded?
Non sarebbe meglio usare qualcosa come un file XML o anche solo un CSV.

o il nome coppie di valori, cioè IA = Iowa
poi caricato in un TStringList per ottenere

States.Values['IA'] = 'Iowa'; 

Allora non vi resta che scrivere qualcosa per cercare i valori di lavorare all'indietro come

//***Untested*** 
//Use: NameOfValue(States, 'Iowa') = 'IA' 

function NameOfValue(const strings: TStrings; const Value: string): string; 
var 
    i : integer; 
    P: Integer; 
    S: string; 
begin 
    for i := 0 to strings.count - 1 do 
    begin 
    S := strings.ValueFromIndex[i]; 
    P := AnsiPos(strings.NameValueSeparator, S); 
    if (P <> 0) and (AnsiCompareText(Copy(S, 1, P - 1), Value) = 0) then 
    begin 
     Result := strings.Names[i]; 
     Exit; 
    end; 
    end; 
    Result := ''; 
end; 

Sono abbastanza sicuro che la sua causa non sia troppo sensibile

+2

+1; come usare una TStringList con coppie nome/valore è una buona soluzione. Non capisco perché sei stato svalutato da altri (è piuttosto scortese parlare di downvote senza lasciare un commento). –

+1

@Christopher Chase: Perché NON dovrebbe essere hardcoded? I nomi e le abbreviazioni degli Stati Uniti sono stati risolti da un po 'di tempo e probabilmente non cambieranno nel prossimo futuro. Metti il ​​tuo nome in un file XML o CSV, insieme alle tue iniziali? (Non downvoting perché è una risposta, anche se IMO non è buona. È come aggiungere un RDBMS alla tua app per memorizzare l'unico nome utente e password dell'utente: overhead, file I/O e codice inutili senza alcun guadagno .) –

+1

@Ken White: con rispetto, non sono d'accordo. Il codice e i dati di missaggio sono icky. Ad esempio, l'errore di ortografia per "South Carolina" che è stato menzionato qui da dthorpe. Se fosse stato nell'eseguibile, sarebbe stato necessario consegnare un nuovo eseguibile, mentre l'errore potrebbe essere più semplice da correggere se i dati fossero stati archiviati in una posizione separata, ad esempio un database centrale. La distribuzione di un numero elevato di file eseguibili nei siti con centinaia di workstation non è qualcosa da prendere alla leggera. –

1

Vorrei che le vostre liste fossero ordinate. In questo modo è possibile utilizzare uno binary search per ridurre i tempi di ricerca. Tutto dipende dal numero di iterazioni che si stanno esercitando. Circa 50 articoli non sembrano molto, finché il tuo iterare sulla lista poche migliaia di volte cerca l'ultimo elemento nell'elenco.

Inoltre, dovresti SEMPRE liberarti dei tuoi loop non appena ottieni una partita se sai che il resto della lista non combacerà.

Gli array vanno bene e, a seconda di come si utilizzano i dati, potrebbe essere necessario aggiungere alcuni dei "territori" che hanno anche abbreviations (PR = PUERTO RICO, GU = GUAM, ecc.).

Problemi correlati