Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,117

    [VB.Net] - Ciclo ricorsivo un po strano...

    Ciao a tutti cercherò di spiegarmi anche se so già che mi incarterò xD

    Premetto che non son mai andata troppo d'accordo coi cicli ricorsivi seppure ne capisca concettualmente il funzionamento mi son sempre un po bloccata

    Allora....io ho una tabella di un database dalla quale pesco i miei dati ed ho una serie di categorie e sotto categorie organizzate così:


    id_cat | parent_id | nome_cat


    ora...come avete capito il campo "parent_id" gestisce l'eventuale sottocategoria (se ha valore 0 la categoria è in testa mentre se ha un valore superiore a zero quel valore è l'id della sua categoria "madre).

    Io mi trovo a dovere creare un sistema di cartelle su windows che rispecchi la struttura delle categorie. Il mio blocco sta nel fatto che non ci sono i "livelli"...cioè se ci fosse stato un altro campo "level_cat" (per dire) avrei potuto creare il primo livello, poi il secondo ecc ecc ma così mi sto bloccando xD
    Per ora ho buttato giù questo ma mi son già piantata xD

    codice:
    Private Sub creazioneCatPath(ByVal mioDs As DataSet, ByVal urlDest As String, ByVal valParent As Integer)
          For Each riga As DataRow In mioDs.Tables("categorie").Rows
                Dim nomePathCat As String = riga("id_cat") & " - " & riga("nome_cat")
                If riga("parent_id") = valParent Then
                      If IO.Directory.Exists(urlDest & nomePathCat) = False Then
                             IO.Directory.CreateDirectory(urlDest & nomePathCat)
                      End If
                End If
          Next
    End sub
    Potete darmi una manina nel ragionamento?

  2. #2
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    non c'è bisogno della ricorsione se lo scopo è solo quello di creare la struttura delle cartelle

    Scorri tutte le categorie ad una ad una, per ognuna di loro:

    - ti crei un array/lista di string/int (il tipo di id_parent)
    - scorri i parent_id a ritroso finche non arrivi a parent_id==0 e aggiungi di volta in volta il parent_id alla lista
    - ordina la lista in ordine crescente, nell'insieme rappresenta la struttura della directory da creare.

    non puoi direttamente creare la directory perche non sai se e quali directory intermedie di livello superiore sono gia state o meno create, perciò partendo dal primo parent_id nella lista ordinata (che è sicuramente uno 0) devi:
    - convertirlo in una path (OCCHIO: tenendo conto di quelli precedenti)
    - controllare se la path esiste e nel caso creare la directory.

    Abbi pazienza, non ho la testa per convertire tutto in codice. Si tratta comunque di un foreach con dentro due cicli while.

  3. #3
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    E' vero che la ricorsione non è mai necessaria, ma questo mi sembra proprio un caso tipicamente ricorsivo.

    Nell'esempio di sotto ho utilizzato una tabella che, in origine mi serviva per creare un menu.
    La stessa tabella mi serve in questo caso per crearmi la struttura di Directory-files su disco.

    le voci principali della tabella sono
    id_menu, tuo id_cat
    text, tuo nome_cat
    id_parent, tuo parent_id
    type, D per directory, F per file

    codice:
    Option Strict On
    
    Partial Class prove_a
        Inherits System.Web.UI.Page
    
        Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
            CreaMenu()
        End Sub
    
        Private Sub CreaMenu()
            'estraggo tutte le voci, file e directory
            Dim dt As DataTable = ora.GetDataTable(gl.StringaConnessione, String.Format("select * from menu where id_modulo = {0} ", 2))
    
            'considero solo i file e le directory di primo livello
            Dim rows As DataRow() = dt.Select("id_parent is null")
            For Each row As DataRow In rows
                Dim id_menu As Integer = CInt(row("id_menu"))
                Dim text As String = l.NullToString(row("text")).Replace("\"c, "_"c).Replace("/"c, "_"c).Replace("|"c, "_"c).Replace("<"c, "_"c).Replace(">"c, "_"c).Replace(":"c, "_"c)
                Dim type As String = l.NullToString(row("type"))
    
                'creo tutta la struttura in c:\tmp per non sporcarmi il computer
                text = String.Format("c:\tmp\{0}", text)
    
                'se directory
                If String.Equals(type, "D", StringComparison.OrdinalIgnoreCase) Then
                    Directory.CreateDirectory(text)
                    PopolaMenu(dt, id_menu, text)
                Else
                    'se file
                    File.CreateText(text)
                End If
    
            Next
    
        End Sub
    
    
        Protected Sub PopolaMenu(dt As DataTable, id_parent As Integer, textParent As String)
            Dim rows As DataRow() = dt.Select(String.Format("id_parent = {0}", id_parent))
            For Each row As DataRow In rows
                Dim id_menu As Integer = CInt(row("id_menu"))
                Dim text As String = l.NullToString(row("text")).Replace("\"c, "_"c).Replace("/"c, "_"c).Replace("|"c, "_"c).Replace("<"c, "_"c).Replace(">"c, "_"c).Replace(":"c, "_"c)
                Dim type As String = l.NullToString(row("type"))
    
                text = String.Format("{0}\{1}", textParent, text)
    
                If String.Equals(type, "D", StringComparison.OrdinalIgnoreCase) Then
                    Directory.CreateDirectory(text)
    
                    'richiamo ricorsivamente PopolaMenu
                    PopolaMenu(dt, id_menu, text)
                Else
                    File.CreateText(text)
                End If
    
            Next
        End Sub
    
    
    End Class
    Pietro

  4. #4
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,117
    scusami piero ma non riesco a usare la classe
    Mi da molti errori ci son da inserire riferimenti o imports per caso?

  5. #5
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    codice:
    Option Strict On
    Imports l = libreria.ModuloWeb
    
    Partial Class CorsoApogeo_ricorsione_iterazione_crea_directory_da_menu
        Inherits System.Web.UI.Page
    
        Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
            CreaMenu()
        End Sub
    
        Private Sub CreaMenu()
            'estraggo tutte le voci, file e directory
            Dim dt As DataTable = ora.GetDataTable(gl.StringaConnessione, String.Format("select * from menu where id_modulo = {0} ", 3))
    
            'creo la struttura delle directroy in c:\tmp
            PopolaMenu(dt, Nothing, "c:\tmp")
    
        End Sub
    
    
        Protected Sub PopolaMenu(dt As DataTable, id_parent As Nullable(Of Integer), textParent As String)
            Dim w As String = ""
            If id_parent.HasValue Then
                w = String.Format("id_parent = {0}", id_parent.Value)
            Else
                w = "id_parent is null"
            End If
    
            Dim rows As DataRow() = dt.Select(w)
            For Each row As DataRow In rows
                Dim id_menu As Integer = CInt(row("id_menu"))
                Dim text As String = l.NullToString(row("text")).Replace("\"c, "_"c).Replace("/"c, "_"c).Replace("|"c, "_"c).Replace("<"c, "_"c).Replace(">"c, "_"c).Replace(":"c, "_"c)
                Dim type As String = l.NullToString(row("type"))
    
                If id_parent.HasValue Then
                    text = String.Format("{0}\{1}", textParent, text)
                Else
                    text = String.Format("c:\tmp\{0}", text)
                End If
    
    
                If String.Equals(type, "D", StringComparison.OrdinalIgnoreCase) Then
                    If Not Directory.Exists(text) Then Directory.CreateDirectory(text)
                    PrintLn(text)
    
                    'richiamo ricorsivamente PopolaMenu
                    PopolaMenu(dt, id_menu, text)
                Else
                    If Not File.Exists(text) Then
                        Using File.Create(text & ".txt")
                        End Using
                    End If
    
                    PrintLn(text & ".txt")
                End If
            Next
        End Sub
    
    
    End Class

    Ho semplificato il codice usando una sola procedura.

    NON PUOI USARE IL CODICE COSI' COME E' ma lo devi prendere come spunto.

    Ad esempio, PrintLn non fa altro che stampare a schermo con response.write, NullToString è una mia funzione che puoi eliminare, ora.GetDataTable è una mia funzione perciò ne devi usare una tua.
    Ripeto, lo devi usare come spunto e lo puoi semplificare ancora di più.
    Pietro

  6. #6
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,117
    ahah ops

    Il problema è che non capendolo al 100% mi viene difficile prenderne spunto perchè ho sempre paura che magari qualcosa che elimino serva al mio scopo! xD

    Ora riprovo

  7. #7
    Utente di HTML.it L'avatar di pietro09
    Registrato dal
    Jan 2002
    Messaggi
    10,116
    un po' di coraggio!

    per esempio, se devi scrivere solo directory, questo codice

    codice:
    If String.Equals(type, "D", StringComparison.OrdinalIgnoreCase) Then
    	If Not Directory.Exists(text) Then Directory.CreateDirectory(text)
    	PrintLn(text)
    
    	'richiamo ricorsivamente PopolaMenu
    	PopolaMenu(dt, id_menu, text)
    Else
    	If Not File.Exists(text) Then
    		Using File.Create(text & ".txt")
    		End Using
    	End If
    
    	PrintLn(text & ".txt")
    End If
    va semplificato con questo
    codice:
    If Not Directory.Exists(text) Then Directory.CreateDirectory(text)

    Se le directory di primo livello hanno come parent zero e non null, sostituisci

    id_parent As Nullable(Of Integer)

    con un semplice Integer

    e
    Dim w As String = ""
    If id_parent.HasValue Then
    w = String.Format("id_parent = {0}", id_parent.Value)
    Else
    w = "id_parent is null"
    End If
    con

    w = String.Format("id_parent = {0}", id_parent)
    Pietro

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.