Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    213

    Errore funzione ricorsiva

    Ho un problema sul quale mi sono bloccato ma non riesco a capirne il perchè visto che la logica mi sembra quella giusta.

    Ho un JSON dal quale devo leggerne i valori stile albero attraverso una funzione ma purtroppo mi va in un loop infinito. Vi posto il codice purtroppo io non riesco a vederlo l'errore forse perchè son convinto che sia la giusta logica

    codice:
        <script>
            function costruisciExp(str) 
            {
                var j = JSON.parse(str);
                
                var risultato = j[0].valore;
                risultato += startBuild(j[0]);
                console.log(risultato);
            }
            
            function startBuild (ogg)
            {
                var risultato = "";
                for (i=0; i<ogg.nodiSub.length; i++) 
                {
                    risultato += ogg.nodiSub[i].valore + ",";
                    if(ogg.nodiSub[i].nodiSub.length != 0)
                    {
                        startBuild(ogg.nodiSub[i]);
                    }
                }
                return risultato;    
            }
        
            var prova = "[{\"valore\":\"DECODE\",\"nodiSub\":[{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]},{\"valore\":\"''\",\"nodiSub\":[]},{\"valore\":\"DOMINIO\",\"nodiSub\":[]},{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]}]}]";
            costruisciExp(prova);
      </script>
    Senza la ricorsione mi funziona bene.
    Confido in un vostro aiuto, grazie.

  2. #2
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Nel ciclo for la variabile i va dichiarata esplicitamente (ad esempio con var o let) in modo che non diventi globale ma sia resa visibile solo nello scope della funzione per ogni specifica chiamata all'interno del ciclo di ricorsione.

    Se questa non viene dichiarata esplicitamente, risulta dichiarata automaticamente a livello globale per cui per ogni ricorsione viene azzerata prima che il corrente ciclo for sia concluso, cioè quando viene eseguita una ricorsione per un successivo livello, in sostanza è come se l'incremento i++ non avvenisse perché la variabile viene comunque azzerata, provocando quindi una ricorsione infinita.

    Puoi risolvere aggiungendo semplicemente var:
    codice:
    for (var i=0; i<ogg.nodiSub.length; i++)
    Probabilmente va rivisto anche il sistema di concatenamento della variabile risultato, da quel che vedo non otteni un albero completo in quel modo.
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    213
    Grazie mille per la precisa risposta. Ovviamente è stato un errore di distrazione che non sono riuscito a correggere perchè non mi dava errore altrimenti avrei sicuramente messo quel var vicino alla i (ma non sapevo che su js andasse anche senza dichiararla) e mi sono trovato ingannato.

    Si purtroppo non riesco a ricostruire bene quell'albero e quindi la stringa che interessa a me. Al momento sono arrivato a questo risultato ma si ferma quando raggiunge una foglia e non passa alle altre. Cosa sbaglio?

    codice:
    	<script>
    		function costruisciExp(str) 
    		{
    			var j = JSON.parse(str);
    			
    			var risultato = j[0].valore + "(";
    			risultato += startBuild(j[0]);
    			console.log(risultato);
    		}
    		
    		function startBuild (ogg)
    		{
    			var stringa;
    			var n = 0;
    			for (var i=0; i<ogg.nodiSub.length; i++) 
    			{
    				n++;
    				stringa = ogg.nodiSub[i].valore;
    				if(ogg.nodiSub[i].nodiSub.length > 0)
    				{
    					stringa += "(";
    					stringa += startBuild(ogg.nodiSub[i]);
    				}
    				if(n != ogg.nodiSub.length)
    					stringa += ",";
    			}
    			
    			stringa += ")";
    			return stringa;
    		}
        
    		var prova = "[{\"valore\":\"DECODE\",\"nodiSub\":[{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]},{\"valore\":\"''\",\"nodiSub\":[]},{\"valore\":\"DOMINIO\",\"nodiSub\":[]},{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]}]}]";
    		costruisciExp(prova);
      </script>

  4. #4
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    (ma non sapevo che su js andasse anche senza dichiararla)
    In JavaScript le variabili non esplicitamente dichiarate vengono dichiarate automaticamente a livello globale, accessibili quindi da qualsiasi ambito di visibilità, cioè da qualsiasi punto nello script.

    Per limitare questo tipo di problematiche si può forzare l'interprete JavaScript ad usare la modalità rigorosa (strict mode).

    Ti è sufficiente inserire la stringa testuale 'use strict'; ad inizio script o ad inizio funzione per attivare questa modalità rispettivamente nell'intero script o per la specifica funzione.

    Questo ti costringe chiaramente ad usare una sintassi più rigida ma ti permette di ottenere, tra le altre cose, un debug più preciso perché vengono segnalati errori (come l'omissione di var, nel tuo caso) che altrimenti, in modalità normale, non verrebbero segnalati.

    Vedi alcuni riferimenti per approfondire:
    Modalità Strict
    Debug veloce con ECMAScript Strict Mode
    Strict mode in Javascript
    Strict mode

    ... Cosa sbaglio?
    Non so ma tutto il passaggio si può semplificare molto. Qui un esempio di come lo imposterei io, usando il metodo map() per ciclare i vari nodiSub.

    codice:
    <script>
       'use strict';
       
       function costruisciExp(str){
          var j = JSON.parse(str)[0];
          console.log(generaAlbero(j));
       }
       function generaAlbero(j){
          return j.valore + (j.nodiSub.length ? '(' + j.nodiSub.map(j=>generaAlbero(j)).join(',') + ')' : '');
       }
       
       var prova = '[{"valore":"DECODE","nodiSub":[{"valore":"TRIM","nodiSub":[{"valore":"DESCRIZIONE","nodiSub":[]}]},{"valore":"\'\'","nodiSub":[]},{"valore":"DOMINIO","nodiSub":[]},{"valore":"TRIM","nodiSub":[{"valore":"DESCRIZIONE","nodiSub":[]}]}]}]';
       costruisciExp(prova);
    </script>
    Non mi pare ci sia molto da spiegare ma se hai bisogno di chiarimenti chiedi pure
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  5. #5
    Utente di HTML.it
    Registrato dal
    May 2012
    Messaggi
    213
    Quote Originariamente inviata da KillerWorm Visualizza il messaggio
    In JavaScript le variabili non esplicitamente dichiarate vengono dichiarate automaticamente a livello globale, accessibili quindi da qualsiasi ambito di visibilità, cioè da qualsiasi punto nello script.

    Per limitare questo tipo di problematiche si può forzare l'interprete JavaScript ad usare la modalità rigorosa (strict mode).

    Ti è sufficiente inserire la stringa testuale 'use strict'; ad inizio script o ad inizio funzione per attivare questa modalità rispettivamente nell'intero script o per la specifica funzione.

    Questo ti costringe chiaramente ad usare una sintassi più rigida ma ti permette di ottenere, tra le altre cose, un debug più preciso perché vengono segnalati errori (come l'omissione di var, nel tuo caso) che altrimenti, in modalità normale, non verrebbero segnalati.

    Vedi alcuni riferimenti per approfondire:
    Modalità Strict
    Debug veloce con ECMAScript Strict Mode
    Strict mode in Javascript
    Strict mode


    Non so ma tutto il passaggio si può semplificare molto. Qui un esempio di come lo imposterei io, usando il metodo map() per ciclare i vari nodiSub.

    codice:
    <script>
       'use strict';
       
       function costruisciExp(str){
          var j = JSON.parse(str)[0];
          console.log(generaAlbero(j));
       }
       function generaAlbero(j){
          return j.valore + (j.nodiSub.length ? '(' + j.nodiSub.map(j=>generaAlbero(j)).join(',') + ')' : '');
       }
       
       var prova = '[{"valore":"DECODE","nodiSub":[{"valore":"TRIM","nodiSub":[{"valore":"DESCRIZIONE","nodiSub":[]}]},{"valore":"\'\'","nodiSub":[]},{"valore":"DOMINIO","nodiSub":[]},{"valore":"TRIM","nodiSub":[{"valore":"DESCRIZIONE","nodiSub":[]}]}]}]';
       costruisciExp(prova);
    </script>
    Non mi pare ci sia molto da spiegare ma se hai bisogno di chiarimenti chiedi pure
    Grazie ancora per l'ulteriore spiegazione, è una cosa di cui ne terrò mente visto che è molto utile.
    Ero già arrivato alla soluzione ieri ma non ho avuto la linea internet per poterlo comunicare.

    Questo è il mio risultato:
    codice:
    	<script>
    		function costruisciExp(str) 
    		{
    			var j = JSON.parse(str);
    			
    			var risultato;
    			risultato = startBuild(j[0]);
    			console.log(risultato);
    		}
    		
    		function startBuild (ogg)
    		{
    			var n = 0;
    			var stringa = ogg.valore + "(";
    			for (var i=0; i<ogg.nodiSub.length; i++) 
    			{
    				n++;
    				if(ogg.nodiSub[i].nodiSub.length > 0)
    				{
    					stringa += startBuild(ogg.nodiSub[i]);
    				} else
    				{
    					stringa += ogg.nodiSub[i].valore;
    				}
    				if(n != ogg.nodiSub.length)
    					stringa += ",";
    			}
    			
    			stringa += ")";
    			return stringa;
    		}
        
    		var prova = "[{\"valore\":\"DECODE\",\"nodiSub\":[{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]},{\"valore\":\"''\",\"nodiSub\":[]},{\"valore\":\"DOMINIO\",\"nodiSub\":[]},{\"valore\":\"TRIM\",\"nodiSub\":[{\"valore\":\"DESCRIZIONE\",\"nodiSub\":[]}]}]}]";
    		costruisciExp(prova);
      </script>
    Ma osserverò anche il tuo per poterlo migliorare, grazie.

  6. #6
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Ma osserverò anche il tuo per poterlo migliorare, grazie.
    di nulla
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

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.