Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    [Pillola] Come gestire le parole all'interno di una stringa

    E' parecchio tempo che ci penso e volevo trovare un modo comodo per gestire le parole di una stringa. Per un uomo è facile capire cosa è una parola all'interno di una stringa, per un pc un pò meno visto che il concetto di "SPAZIO" inteso come bianco o no rappresenta nei vari linguaggi qualcosa di confusionario e fumoso. Penso sia capitato a tutti aver un testo lungo e volerne presentare una parte ai suoi utenti, magari corredata da un link [leggi tutto] per leggere il resto. Un esempio pratico è l'indice di alcuni articoli.
    Un modo che sovraccarica poco il server e che evita troppi pensieri al programmatore sarebbe usare substr() e prendere un pezzetto della stringa, ma il rischio di troncare una parola è troppo alto ed in questo caso l'effetto è davvero pessimo.
    L'altra idea sarebbe usare una split sugli spazi, ma immaginiamo che abbiamo una stringa le cui parole son separate da caratteri che non sono spazi? Che succede?
    Per ovviare a questo problema ecco la mia pillola.

    Le funzioni di cui faremo uso sono 3:

    codice:
    /* ### CONTA IL NUMERO DI PAROLE DI UNA STRINGA ### */
    function	wordsCounter($fStrWords){
    
    		$iTotalBlankSpaces=charCounter($fStrWords," ");
    		$iTotalCRLF=charCounter($fStrWords,"\n");
    		$iTotalHorTab=charCounter($fStrWords,"\t");
    
    		/* ### SI AGGIUNGE UNO PERCHE' IN REALTA' CONTIAMO I SEPARATORI E NON LE PAROLE ### */
    		$iTotalWords=$iTotalBlankSpaces + $iTotalCRLF + $iTotalHorTab+1;
    		
    		return $iTotalWords;
    
    } 
    
    
    
    /* ### CONTA IL NUMERO DI OCCORRENZE DEL CARATTERE ### */
    function	charCounter($fStrWords,$fCharTarget){
    
    		$arrOccurrences=count_chars($fStrWords,1);
    		
    		$iAsciiCode=ord($fCharTarget);
    
    		if	(isset($arrOccurrences[$iAsciiCode])){
    			$iOccurrences=$arrOccurrences[$iAsciiCode];
    		}else{
    		        $iOccurrences=0;
    		}
    		
    		return $iOccurrences;
    }
    
    /* ### SELEZIONA LE PRIME N PAROLE DALLA STRINGA ### */
    function	getWords($fStrWords,$fIntNumber){
                    
    		$iEffWord=wordsCounter($fStrWords);
    		
    		if	($iEffWord>$fIntNumber){
    
    			$fStrWords=str_replace("\n\r","\n",$fStrWords);
    			$fStrWords=str_replace("\r\n","\n",$fStrWords);
    			$fStrWords=str_replace("\r","\n",$fStrWords);
    
    			$arrWords=split("[ \t\n]",$fStrWords);
    			           
    			$strStoreSplitted=""; 
    			$strStoreJoined="";
    
    			for	($s=0;$s<$fIntNumber;$s++){
    			 
    				$strSplitted=$arrWords[$s];   
    				$strStoreSplitted.=$strSplitted;	   
    				
    			 	$iSeparatorPosition=strlen($strStoreSplitted)+$s;
    				
    				$chrOldSeparator=substr($fStrWords,$iSeparatorPosition,1);
    				
    			        switch	($chrOldSeparator){
    				         case	"\t":
    				         	$chrNewSeparator="\t";
    				         	break;
    			         	case	"\n":
    			         		$chrNewSeparator="\n";
    			         		break;
    			         	default :                  
    				         	$chrNewSeparator=" ";
    				         	break;
    			        }
    				        
    				$strStoreJoined.= $strSplitted . $chrNewSeparator;      
    			}
    			
    			$strWords=$strStoreJoined  . "...";
    			
    		}else{
    			$strWords=$fStrWords;
    		}
    		
    		return $strWords;
    }
    la funzione charCounter esegue un semplice conteggio di del carattere specificato come parametro e ne restituisce il numero di occorrenze. In questo caso è facile vedere che contiamo tutti i tipi di caratteri che possono modellare uno spazio. Io ho preso come esempio caratteri di newline, spazi bianchi e tab, ma se qualcuno avesse bisogno di considerarne altri può tranquillamente aggiungerne.
    Da notare il parametro 1 nella funzione count_chars che evita che vengano restituiti nell'array i caratteri con occorrenza zero e quindi di sovraccaricare troppo la memoria.
    Una volta conteggiati li sommiamo incrementando di uno il risultato perché ricordatevi che stiamo contanto i separatori e non le parole direttamente. Quindi tra due parole ci sarà un solo separatore.
    Una cosa importantissima che devo far notare è che è indispensabile che alla funzione wordsCounter() venga passata una stringa pulita con trim() altrimenti il risultato non sarà preciso.
    La funzione getWords() è invece il risultato che ci interessa maggiormente. Dopo aver contato le parole effettuamo una replace in modo da gestire meglio il concetto di A CAPO che in php è formato da due caratteri e non da uno solo. Evitando queste righe ho visto facendo un pò di prove che possiamo aver comportamenti imprevedibili.
    A questo punto usiamo la funzione split con un espressione regolare. in questo caso: "[ \t\n]". Ovviamente questa espressione è direttamente collegata al tipo di carattere che vogliamo considerare come spazio. Come ho detto prima in questo esempio gli spazi sono gli spazi bianchi, i tab e gli a capo.
    Una split in questo modo spezza la stringa ogni volta che incontra un carattere simile.
    A questo punto dobbiamo ricomporre la stringa considerando le prime N parole (dove N è il secondo parametro) facendo però attenzione di ripristinare il vecchio separatore (se tra due parole c'è un tab, ci deve essere un tab anche nella stringa ricomposta, se no che macello combiniamo :P).
    Fatto questo corrediamo la nostra stringa spezzata dai classici ... della tradizione e la restituiamo.
    Ovviamente se la stringa ha meno parole di quelle da noi richieste sarà restituita intera e senza i puntini di sospensione!
    Spero che la pillola sia utile a tutti coloro che vogliono aver un metodo immediato per presentare dei brani di testo (articoli, avvisi, news) in maniera semplice e senza cedere al compromesso degli spazi.
    I dilettanti costruirono l'Arca, i professionisti il Titanic!

  2. #2
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Ciao nunkij. L'unico problema delle tue funzioni è quello relativo agli apostrofi. Me lo sono posto spesso anche io.

    Se ho ad esempio una stringa così:
    $stringa = "L'altra questione da risolvere è quella relativa agli apostrofi";
    echo getWords($stringa,3);
    Mi restituirà "L'altra questione da" e quindi in realtà quattro parole e non tre.

    Stesso discorso per il conteggio delle parole
    echo wordsCounter($stringa);
    Mi restituirà 9 anzichè 10.

    La mia non vuole essere una critica ma una richiesta a qualcuno più esperto se è in grado di ovviare a questo "inconveniente".


  3. #3
    mmmm hai sollevato una bella questione a cui non ci avevo pensato! Premesso che è da aspiranti suicidi spezzare una stringa con le parole separate dall'apostrofo, però per completezza andrebbe inserito un supporto simile. Ci guarderò meglio appena ho tempo ma penso (e spero) che basti una modifica alla stringa di espressioni regolari per inserire uno split anche in presenza di un apostrofo.
    I dilettanti costruirono l'Arca, i professionisti il Titanic!

  4. #4
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Originariamente inviato da Nunkij
    mmmm hai sollevato una bella questione a cui non ci avevo pensato! Premesso che è da aspiranti suicidi spezzare una stringa con le parole separate dall'apostrofo, però per completezza andrebbe inserito un supporto simile. Ci guarderò meglio appena ho tempo ma penso (e spero) che basti una modifica alla stringa di espressioni regolari per inserire uno split anche in presenza di un apostrofo.
    Farò il tifo per te.Ciao.

  5. #5
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Sono andato a cercare nel forum una domanda che avevo fatto tanto tempo fa attinente a questa discussione.
    Allora ciò che mi serviva era recuperare l'inizio e la fine di una stringa. Volevo ad esempio recuperare le prime tre parole e volevo che quelle separate dall'apostrofo mi venissero considerate due distinte.


    fabi080 mi aveva sfornato queste belle regexp.
    Codice PHP:
    function firstwords($text$n) { 
      return 
    preg_match('/^([^a-z]*[a-z]+){'.$n.'}/i'$text$matches) ? $matches[0] : $text


    function 
    lastwords($text$n) { 
      return 
    preg_match('/([a-z]+[^a-z]*){'.$n.'}$/i'$text$matches) ? $matches[0] : $text


    $text "L'altra questione da risolvere è quella relativa agli apostrofi"
    //var_dump(firstwords($text, 4)); 
    //var_dump(lastwords($text, 4));

    echo firstwords($text3); // Restituisce L'altra questione
    echo "
    "
    ;
    echo 
    lastwords($text3); // relativa agli apostrofi 
    Quindi il problema della parte iniziale è risolto.
    Purtroppo essendo a livello zero in quanto a espressioni regolari non saprei invece come integrarle per il conteggio delle parole.

  6. #6
    Per contare le parole forse potrebbe bastare una cosa tipo:
    codice:
    function wordCount($str){
    	return preg_match_all('/\b\w+\b/',$str,$null);
    }
    
    
    
    // e questa per contare le prime n parole
    function firstNwords($str,$n){
    	return preg_replace('/((\b\w+\b.*?){'.$n.'}).*$/s','$1',$str);
    }
    dA .. foto di viaggio
    L'esperienza è il tipo di insegnante più difficile.
    Prima ti fa l'esame, e poi ti spiega la lezione.

  7. #7
    Utente di HTML.it L'avatar di nicola75ss
    Registrato dal
    Nov 2004
    Messaggi
    12,923
    Ciao anakin. Ho fatto un pò di prove con le tue espressioni e sembrano funzionare perfettamente.
    Complimenti! Quando si parla di queste cose arrivi puntuale come le tasse.
    Avrei un'altra domanda da porvi.
    In merito alla funzione charCounter() di nunkij non sarebbe sufficiente la funzione substr_count() di php?

  8. #8
    Originariamente inviato da nicola75ss
    Ciao anakin. Ho fatto un pò di prove con le tue espressioni e sembrano funzionare perfettamente.
    Complimenti! Quando si parla di queste cose arrivi puntuale come le tasse.
    Avrei un'altra domanda da porvi.
    In merito alla funzione charCounter() di nunkij non sarebbe sufficiente la funzione substr_count() di php?
    è che le espressioni regolari sono un po' il mio passatempo, tipo sudoku o come si chiama E poi è un ottimo esercizio per tenerle sempre fresche in mente.
    dA .. foto di viaggio
    L'esperienza è il tipo di insegnante più difficile.
    Prima ti fa l'esame, e poi ti spiega la lezione.

  9. #9
    BUMP
    Addio Aldo, amico mio... [03/12/70 - 16/08/03]

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.