Share |

martedì 16 marzo 2010

Javascript: Utilizzare gli Array Associativi

In questo articolo proporrò alcuni script javascript per documentare una tecnica di utilizzo degli Array Associativi che adopero spesso e che ritengo molto valida per evitare ogni volta di scorrere un array per trovare l'oggetto cercato.

Cos'è un Array Associativo?

Con il termine Associativo si fa riferimento alla possibilità di poter abbinare un oggetto, o un valore da conservare, con un token o chiave che non sia necessariamente un numero, solitamente l'indice del array.

Esempio:

/* Utililzzo tradizionale per indice */
var arr = new Array();
arr[0] = 'xxxx';
arr[1] = 'tttt';
arr[2] = 'aaaa';

/* Utililzzo per associazione */
var arr = new Array();
arr['x'] = 'xxxx';
arr['t'] = 'tttt';
arr['a'] = 'aaaa';

Chi sviluppa in Java utilizza per questo genere di soluzioni un'istanza della classe java.util.Map.

Perchè e quando usarli?

L'esempio concreto che descriverò in questo articolo riguarda proprio il modo con cui ho affrontato e risolto un problema nato durante l'analisi del progetto di rifacimento di un sito.

Una delle specifiche assegnate era la totale separazione dei contenuti dal modo in cui essi sarebbero stati presentati nel sito.

Scelsi quindi di utilizzare XML come fonte dati e javascript per la realizzazione dell'interfaccia client.

Nacque quindi il problema di come poter individuare e trasformare in link solo determinate parole mischiate in tutto il contenuto da mostrare.

L'idea che ho avuto è stata di parsare ogni singola parola del documento al
caricamento della pagina e confrontarla con una serie di elementi contenuti in un array per eventualmente trasformare la parola letta in un link HTML.

Inizialmente il mio array era stato creato tradizionalmente, in questo modo:

var link = new Array();

link[0] = {'key':'java','value':'http://java.sun.com/reference/api/'};
link[1] = {'key':'xml','value':'http://www.w3schools.com/xml/'};
link[2] = {'key':'http://java.sun.com/j2se/javadoc/writingdoccomments/'
    ,'value':'http://java.sun.com/j2se/javadoc/writingdoccomments/'};
link[3] = {'key':'sun','value':'http://www.sun.com'};
link[4] = {'key':'j2ee','value':'http://java.sun.com/javaee/'};
link[5] = {'key':'j2me','value':'http://java.sun.com/javame/'};
link[6] = {'key':'jme','value':'http://java.sun.com/javame/'};
link[7] = {'key':'struts','value':'http://struts.apache.org/'};
link[8] = {'key':'poi','value':'http://poi.apache.org/'};

E il confronto lo eseguivo con una funzione simile a questa:

function confronta(parola){
  for(var i=0; i<link.length; i++){
    if(parola.toUpperCase() == link[i].key.toUpperCase())
      return '<a href="' + link[i].value + '">' + parola + '<a>';
  }
  return parola;

Fino a che l'array era composto di pochi elementi, diciamo una cinquantina di elementi, scorrerlo e confrontare ogni parola del documento XML con la proprietà key di ogni suo elemento non sembrava pesare più di tanto, ma con il crescere del numero di informazioni da conservare e dei termini da confrontare il procedimento era diventato molto pesante: IE aveva dei tempi di risposta veramente insopportabili! :(

Dovevo trovare una soluzione migliore.
Così introdussi l'utilizzo degli array associativi ottenendo una risposta a livello di performance veramente eccezionale ed imprevista: il risultato del procedimento di ricerca e trasformazione in link HTML era presso che immediato e le risorse impegnate sul client sono diminuite di circa il 69% rispetto alla soluzione precedentemente utilizzata.

Quindi il mio array diventò:

var link = new Array();

link['java'] = 'http://java.sun.com/reference/api/';
link['xml'] = 'http://www.w3schools.com/xml/';
link['http://java.sun.com/j2se/javadoc/writingdoccomments/'] 
    = 'http://java.sun.com/j2se/javadoc/writingdoccomments/';
link['sun'] = 'http://www.sun.com';
link['j2ee'] = 'http://java.sun.com/javaee/';
link['j2me'] = 'http://java.sun.com/javame/';
link['jme'] = 'http://java.sun.com/javame/';
link['struts'] = 'http://struts.apache.org/';
link['poi'] = 'http://poi.apache.org/';

Utilizzando questa tipologia di struttura dati il procedimento per eseguire il confronto si è ridotto ad una semplice funzione simile a questa:

function confronta(parola){
  var t = link[parola.toLowerCase() + ''];
  return (t != null && t.length > 0) 
    ? '<a href="' + t + '">' + parola + '</a<' 
    : parola;
}

Conclusioni

Cosa dire?
Non esiste proprio paragone! :)

La differenza è abissale: nel primo approccio, ogni parola del documento doveva essere confrontata con ogni elemento dell'array fino a quando non si verificava il match tra i termini, e siccome per la maggior parte delle parole il match non avveniva, immagina quanti giri a vuoto e risorse sprecate ogni volta produceva la scansione !!!

Differentemente nel secondo approccio, potendo sfruttare una corrispondenza univoca tra la parola da trasformare in link e la chiave di accesso all'array, viene evitata completamente la ricerca all'interno dell'array riducendo notevolmente tempi di attesa e risorse impegnate.

Consiglio di valutare l'ipotesi di utilizzare questa tecnica ogni volta che sia possibile.

Alla prossima,
MA.

0 commenti:

Posta un commento

Non ti è chiaro qualcosa?
No problem, posta il tuo dubbio ;)

..... e ricordati di firmarlo!