Domanda

Vorrei scrivere una JavaScript che convalida un codice postale, controllando se il codice postale esiste effettivamente. Ecco un elenco di tutti i codici postali:

http://www.census.gov/tiger/tms/gazetteer /zips.txt (mi interessa solo la seconda colonna)


Questo è davvero un problema di compressione. Mi piacerebbe farlo per divertimento. OK, ora è fuori mano, ecco un elenco di ottimizzazioni su una tabella diretta che mi viene in mente, mi sento libero di aggiungere qualsiasi cosa a cui non ho pensato:

  • Suddividi il codice postale in 2 parti, le prime 2 cifre e le ultime 3 cifre.
  • Crea un'istruzione if-else gigante controllando prima le prime 2 cifre, quindi controllando gli intervalli tra le ultime 3 cifre.
  • Oppure, converti le zip in esadecimale e vedi se riesco a fare la stessa cosa usando gruppi più piccoli.
  • Scopri se nell'intervallo di tutti i codici postali validi ci sono più codici postali validi rispetto a codici postali non validi. Scrivi il codice sopra indicato per il gruppo più piccolo.
  • Suddividi l'hash in file separati e caricali tramite Ajax come tipi di utente nel codice postale. Quindi forse dividi in 2 parti, prima per le prime 2 cifre, seconda per le ultime 3.

Infine, ho intenzione di generare i file JavaScript utilizzando un altro programma, non a mano.

Modifica: le prestazioni contano qui. Voglio usare questo, se non fa schifo. Esecuzione dell'esecuzione del codice JavaScript + tempo di download.

Modifica 2: solo soluzioni JavaScript, per favore. Non ho accesso al server delle applicazioni, inoltre, ciò trasformerebbe questo in un altro problema =)

È stato utile?

Soluzione

  

Vorrei scrivere una funzione JavaScript che convalida un codice postale

Potrebbe essere più sforzo di quanto valga la pena, tenerlo aggiornato in modo che il codice postale valido valido di qualcuno non venga mai rifiutato. Potresti anche provare un servizio esterno o fare quello che fanno tutti gli altri e accettare qualsiasi numero di 5 cifre!

  

ecco un elenco di ottimizzazioni su una tabella hash diretta che mi viene in mente

Mi dispiace rovinare il potenziale Fun, ma probabilmente non gestirai prestazioni effettive molto migliori di quelle offerte dall'oggetto JavaScript se usato come hashtable. L'accesso ai membri dell'oggetto è una delle operazioni più comuni in JS e sarà super ottimizzato; è improbabile che costruire le proprie strutture dati possa battere anche se si tratta di strutture potenzialmente migliori dal punto di vista dell'informatica. In particolare, qualsiasi cosa che usi "Array" non funzionerà come credi perché Array è effettivamente implementato come un oggetto (hashtable) stesso.

Detto questo, un possibile strumento di compressione dello spazio, se hai solo bisogno di sapere 'valido o no', sarebbe usare un campo bit da 100000 bit, impacchettato in una stringa. Ad esempio per uno spazio di soli 100 codici postali, in cui i codici 032-043 sono "validi":

var zipfield= '\x00\x00\x00\x00\xFF\x0F\x00\x00\x00\x00\x00\x00\x00';
function isvalid(zip) {
    if (!zip.match('[0-9]{3}'))
        return false;
    var z= parseInt(zip, 10);
    return !!( zipfield.charCodeAt(Math.floor(z/8)) & (1<<(z%8)) );
}

Ora non ci resta che trovare il modo più efficiente per portare il bitfield allo script. L'ingenua versione riempita '\ x00' sopra è piuttosto inefficiente. Approcci convenzionali per ridurre questo sarebbe ad es. per codificarlo in base64:

var zipfield= atob('AAAAAP8PAAAAAAAAAA==');

Ciò porterebbe i 100000 flag fino a 16,6kB. Sfortunatamente atob è solo Mozilla, quindi un altro decodificatore base64 sarebbe necessario per altri browser. (Non è troppo difficile, ma è un po 'più tempo di avvio per la decodifica.) Potrebbe anche essere possibile utilizzare una richiesta AJAX per trasferire una stringa binaria diretta (codificata nel testo ISO-8859-1 in responseText). Ciò porterebbe a 12,5 KB.

Ma in realtà probabilmente qualsiasi cosa, anche la versione ingenua, farebbe tutto il tempo in cui hai servito lo script usando mod_deflate, che comprimerebbe molta di quella ridondanza, e anche la ripetizione di '\ x00' per tutte le lunghe distanze di codici "non validi".

Altri suggerimenti

Potresti fare l'impensabile e trattare il codice come un numero (ricorda che in realtà non è un numero). Converti il ??tuo elenco in una serie di intervalli, ad esempio:

zips = [10000, 10001, 10002, 10003, 23001, 23002, 23003, 36001]
// becomes
zips = [[10000,10003], [23001,23003], [36001,36001]]
// make sure to keep this sorted

quindi per testare:

myzip = 23002;
for (i = 0, l = zips.length; i < l; ++i) {
    if (myzip >= zips[i][0] && myzip <= zips[i][1]) {
        return true;
    }
}
return false;

questo sta solo usando una ricerca lineare molto ingenua (O (n)). Se hai mantenuto l'elenco ordinato e utilizzato la ricerca binaria, potresti ottenere O (log n).

Uso API di Google Maps per verificare se esiste un codice postale.

È più preciso.

Supponendo che tu abbia le zip in un array ordinato (sembra giusto se stai controllando la generazione della struttura di dati), vedi se una semplice ricerca binaria è abbastanza veloce.

Quindi ... Stai eseguendo la convalida lato client e vuoi ottimizzare le dimensioni del file? probabilmente non puoi battere la compressione generale. Fortunatamente, la maggior parte dei browser supporta gzip per te, quindi puoi usarlo gratuitamente.

Che ne dici di un semplice dict codificato in json o di un elenco con i codici postali in ordine ordinato e dare un'occhiata al dict. comprimerà bene, dal momento che è una sequenza prevedibile, si importa facilmente dal momento che è json, usando il parser integrato nel browser, e la ricerca sarà probabilmente anche molto veloce, dal momento che è una primitiva javascript.

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