Eliminare duplicati da una lista e ordinarla
Mi è capitato spesse volte di avere una lista di valori, numerici o alfanumerici, e dover eliminare i duplicati.
Tra i vari tentativi, ho scritto codice per eseguire loop in array, creazione di query con successivi loop e ordinamenti, assegnazioni in variabili.
La strada più veloce che ho trovato di recente è quella di utilizzare una struttura.
La struttura infatti di default non accetta duplicati. Vediamo come.
Supponiamo di avere una lista di valori del tipo seguente:
Definizione della lista di prova
// --->
<cfset miaLista = "coldfusion,ajax,coldfusion,bit,byte,bit">
con il seguente semplice codice è possibile creare una struttura priva di duplicati e successivamente ordinarla in modo alfabetico.
Si deve tenere presente che la struttura per sua definizione non permette la creazione di duplicati e quindi porta direttamente alla soluzione del problema
crea struttura vuota per ospitare i nostri dati non duplicati
--->
<cfset TempStruct = {} />
<cfloop list="#miaLista#" index="i">
<!---
popola e toglie duplicati in quanto la
struttura non ammette duplicati :)
--->
<cfset TempStruct[i] = i />
</cfloop>
<!---
al termine del loop esegue ordinamento alfabetico
--->
<cfset Array_Tags = StructSort(TempStruct, 'text', 'asc')>
La logica di ordinamento termina qui. E' la strada più breve che ho trovato al momento.
Se vogliamo ottimizzare il codice e renderlo disponibile al riuso è necessario registrarlo nei componenti e quindi creare una nuova funzione. Tale funzione, che sarà registrata in un file .cfc, eseguirà una query sul mio database, leggerà i valori da una query, eseguirà il codice di pulizia dei duplicati per restituire la lista dei valori ordinati in alfabetico creascente. Vediamo come.
<cffunction name="getMyBlogTags" access="public" returntype="array"
output="false" hint="Seleziona Tags, elimina duplicati e ordina">
<cfargument name="id_cat" type="numeric"
default="0" required="false">
<cfargument name="maxrows" type="numeric"
default="50" required="false">
<cfquery name="sel_tags" datasource="#request.datasource#"
maxrows=#maxrows#>
SELECT distinct tags, visite FROM MyCms_doc
WHERE 0=0
and id_cat = <cfqueryparam value="#id_cat#" cfsqltype="CF_SQL_INTEGER">
AND tags IS NOT NULL
order by visite desc
</cfquery>
<!---
crea struttura
--->
<cfset TempStruct = {} />
<!---
esegue un ciclo di loop sugli elementi estratti dalla query
si tenga presente che gli elementi per ogni record sono di questo tipo:
rec1: coldfusion,jquery
rec2: jquery,coldfusion,bit,byte
rec3: bit,jequery
quindi il valuelist concatena gli elementi arrivando a questo:
coldfusion,jquery,jquery,coldfusion,bit,byte,bit,jequery
--->
<cfloop list="#valuelist(sel_tags.tags)#" index="i">
<!---
popola e toglie duplicati in quanto la stru non ammette duplicati :)
--->
<cfset TempStruct[i] = i />
</cfloop>
<!---
esegue ordinamento
--->
<cfset Array_Tags = StructSort(TempStruct, 'text', 'asc')>
<!---
ritorna un Array senza duplicati e correttamente ordinato
--->
<cfreturn Array_Tags>
</cffunction>
</cfcomponent>
Il componente visto sopra, è quello utilizzato in questo Blog per mostrare i Termini Cloud. Per utilizzare la funzione è sufficiente fare un Invoke del componente oppure referenziarlo come oggetto di memoria nel seguente modo:
Chiama il componente e memorizza l'array risultato
--->
<cfset Blog_Tags = application.componenti.getMyBlogTags(id_cat='2',maxrows='20')>
<!---
A questo punto esegue un semplice output dell'array
--->
<cfloop array="#Blog_Tags#" index="tag">
<cfoutput>
<a href="MioLink_To">#tag#</a>
</cfoutput>
</cfloop>
Fine. Attendo commenti