Newsgroup: it.comp.appl.access
Titolo: Concatenazione & Riconcatenazione stringhe

Premesssa: cerco soluzione "accattivante".
Una soluzione qualsiasi richiede solo olio di polpastrello.
Struttura file  (e' un file di testo)
[Nome1]
      key=blabla
      [.Nome2]   -->da concatenare a nome1
         -->keys
      [.]   fine subsezione
      [.Nome3] --> questa deve essere concatenata a Nome1
	-->keys
      [.Nome4] --> questa deve essere concatenata a Nome3
	--> keys
      [..Nome5] --> questa concatena a Nome3
	--> Keys
[Nome6.Nome7.Nome8.Nome9] sostituiscono da Nome1
	-->keys   (appese a nome9)
      [...Nome10] da appendere a Nome7
Situazione finale
[Nome1]
     [Nome2]
     [Nome3]
          [Nome4]
          [Nome5]
[Nome6]
     [Nome7]
          [Nome8]
               [Nome9]
     [Nome10]
In sostanza il "." e' un delimitatore di gerarchia.
1) Se non c'e',come primo carattere, genera una nuova radice.
2) Se ce ne e' uno la chiave viene appesa alla precedente
3) Se ne e' presente piu' di uno il numero di punti - 1 da il livello di 
risalita
4) Se i punti sono da soli il livello di risalita e' pari al numero di 
punti.
5) La gerarchia non deve avere limitazioni.
Per chi le conosce, posso usare le espressioni regolari
Se poi non mi sono spiegato vi "sbatto" qui il file da gestire
Thanks anticipati
--
ac

 Se poi non mi sono spiegato vi "sbatto" qui il file da gestire
Alle brutte... ma che linguaggio useresti per fare questa cosa?
ciao,
Panathos

 Per chi le conosce, posso usare le espressioni regolari
Con le regexp puoi differenziare se ci sono puntini, se ce n'è uno o
più consecutivi, se ci sono più punti non consecutivi... ma tu
dovresti anche estrarre i [nomi] laddove ce n'è più di uno sulla
stessa riga, separato da non-sai-quanti puntini (e non puoi saperlo
dalla regexp, perché queste non fanno conteggi).
Dovresti cominciare il ciclo per il primo array con la variabile
numTabulazioni = 0, e poi aumentare o diminuire in base ai match che
ottieni facendo un for -next sui caratteri di ogni riga acquisita.
ciao,
Panathos

 Per chi le conosce, posso usare le espressioni regolari
Con le regexp puoi differenziare se ci sono puntini, se ce n'è uno o


 Alle brutte... ma che linguaggio useresti per fare questa cosa?
In questo caso sto usando java, ma fa lo stesso. Con access c'e' una 
piccola complicanza dovuta alle espressioni regolari ma la sostanza 
dovrebbe rimanere la stessa. Una libreria per le regex c'e' anche per 
Access, o comunque il modo di "giragliintorno" si trova.
"hopeando" di aver chiarito.
Ciao Fabrizio
--
ac

 
[cut]
Ariciao
--
ac

 Questo e' un pezzo di file vediamo se si capisce meglio
Sì e per il pattern matching qualche idea un po' contorta ce l'avrei,
anche se -vista la provenienza del file- non credo che avrai davvero
una roba tipo questa:
[.....Nome6...Nome7Nome8..Nome9]
passi per i riferimenti prima di [nome6], ma [nome7] e [nome8] erano
prive del punto fra loro  :-)
cmq vediamo questi casi liberamente tratti dagli esempi:
[.....Nome6...Nome7Nome8..Nome9]
[axn.com.dictionary.accessori]
[..Sounder]
[.MDB]
[.]
io per ogni stringa farei due sostituzioni con regexp, globali, in
modo da "normalizzarla", poi con due split avrei il "riferimento" per
ciascun elemento, ed il suo nome.
Cerco di spiegarmi in metacazzlinguaggio:
s = "[.....Nome6...Nome7.Nome8..Nome9] "
' togliamo le parentesi quadre...
s1 = replace(s, array('[',']')
' trasformo tutti i punti multipli in uno solo per poi splittare
s1 = regReplaceGlobal(s1, "\.+", "\.")
' splitto il punto per ottenere le classi
arrClassi = split(s1, '.')
arrClassi = 'Nome6', 'Nome7', 'Nome8', 'Nome9'
' anche in Java ogni elemento dell'array è indicizzato numericamente a
partire da zero...
Dopodiché ottengo il riferimento per ciascuna classe:
' trasformo tutti i caratteri non-punti un separatore unico qualsiasi,
da splittare
s1 = regReplaceGlobal( s1, "[^\.]+", "A")
' s1 = ".....A...A.A..A"
' splitto per ottenere un array con i riferimenti delle classi
arrRif = split(s1, "A")
arrRif = '.....', '...', '.', '..', Null
' arrClassi è di 4 elementi, arrRif ne ha 5 di cui l'ultimo non serve
' la lunghezza della stringa di ciascun elemento di arrRif restituisce
il riferimento relativo alla classe attuale, da agganciare in un altro
array se non si usano array associativi:
foreach elem in arrRif {
  arrDist[] = strlen(elem)
}
Ora si ottiene:
arrClassi = 'Nome6', 'Nome7', 'Nome8', 'Nome9'
arrRif = '.....', '...', '.', '..', Null
arrDist = 5, 3, 1, 2
arrDist ti fornisce il "riferimento relativo" per ogni elemento di
arrClassi; poi gestirlo bene è un altro film... perché i riferimenti
sono relativi, e quindi ti devi tirare dietro un altro array che
appunto viene riferito... e per come la vedo io per gestire bene i
"casi" di match qui sopra converrebbe usare una switch() anche solo
per matchare il [.] senza scasinare con le regexp... ma mi fermo qui e
attendo tua reply.
ciao,
Panathos

 Panathos
Non uso array. In access uso una collezione mentre in Java al momento 
una HasMap (piu' o meno e' la stessa cosa).
Il problema di assegnare e ritrovare i dati non lo ho. Quella parte e'
risolta da tempo.
Il problema e' solo come formattare la stringa da avviare al metodo di
inserimento delle chiavi.
Il metodo getSezione viene chiamato in questo modo
if left(trim(linea),1) = "[" then
     nuovasezione=getSezione(sezioneprecedente,lineaditesto)
else
   --> appende alla sezione corrente la chiave descrittiva
   es Tipo=Erbaceaa
end if
il problema e' solo costruire la nuova sezione
immmagina che le chiamate siano cosi' (metto gia' il risultato atteso 
con -->)
1
getSezione("Fanerogame.Orchidacee.Ophrys.Ophrys 
Apifera","[..Neottia.Neottia NidusAvis]" 
-->"Fanerogame.Orchidacee.Neottia.Neottia NidusAvis"
2
getSezione("Fanerogame.Orchidacee.Neottia.Neottia Nidus Avis","[...]" 
--> "Fanerogame"
3
getSezione("Fanerogame","[.Labiate.Thymus]"
--> "Fanerogame.Labiate.Thymus"
4
getSezione("Fanerogame.Labiate.Thymus","[.Thymus Serpyllum]"
--> "Fanerogame.Labiate.Thymus.Thymus Serpyllum"
5
getSezione("Fanerogame.Labiate.Thymus.Thymus 
Serpyllum","[Crittogame.Equisetacee.Equisetum.Equisetum Arvense]"
--> "Crittogame.Equisetacee.Equisetum.Equisetum Arvense"
Inoltre parto dal presupposto che la riga da gestire sia formalmente 
corretta se non lo e' si arrangino. (Comunque la soppressione dei punti 
che eventualmente sono di troppo viene fatta in fase di scrittura della 
chiave)
i.e. se in scrittura chiave mi arriva una cosa cosi':
".x...t.z..v.....n"
diventa
"x.t.z.v.n"
Una mezza soluzione la ho buttata giu'. Devo solo testarla.
Poi chiedero' "aiuto" per migliorarla.
Ovviamente anche la gestione Access.
--
ac

 --> "Crittogame.Equisetacee.Equisetum.Equisetum Arvense"
E anche questo va bene, non ci sono punti e deve restituire la classe
del secondo argomento.
Cmq mi sono intrippato e ti mando un codice funzionante per il parsing
"come l'ho inteso", dimmi un po' tu.
Sub VBtrip()
Dim coll1 As New Collection, arg1$, arg2$, stringa$
Dim arr1arg, arr2arg, i%, elem
arg1 = "Fanerogame.Orchidacee.Ophrys.Ophrys Apifera"
arg2 = ".Labiate"
arr1arg = Split(arg1, ".")
For Each elem In arr1arg
    coll1.Add elem
Next elem
arr2arg = Split(arg2, ".")
If UBound(arr2arg) = 0 Then
    Set coll1 = Nothing
    coll1.Add arr2arg(0)
End If
For i = 0 To UBound(arr2arg)
    If arr2arg(i) = "" And i = 0 Then
        GoTo prosegui
    ElseIf arr2arg(i) = "" And i <> UBound(arr2arg) Then
        coll1.Remove coll1.Count
    Else
        If arr2arg(i) <> "" Then coll1.Add arr2arg(i)
    End If
prosegui:
Next i
For Each elem In coll1
    stringa = "" & stringa & elem + "."
Next elem
stringa = Left(stringa, Len(stringa) - 1)
Debug.Print stringa
End Sub
ciao,
Panathos

 wrote:
Questo è il codice corretto. Alla routine postata precedentemente
mancava l'istruzione su cosa fare quando veniva passata una classe
senza riferimento.
Ho dato per scontato che le parentesi quadre non ci fossero fin
dall'inizio, come vedi.
Sub prova_VBtrip()
MsgBox VBtrip("Fanerogame.Orchidacee.Ophrys.Ophrys Apifera",
"...Neottia.Neottia NidusAvis")
End Sub
Function VBtrip(arg1, arg2) As String
Dim coll1 As New Collection
Dim arr1arg, arr2arg, i%, elem
Dim stringa$
arr1arg = Split(arg1, ".")
For Each elem In arr1arg
    coll1.Add elem
Next elem
arr2arg = Split(arg2, ".")
If UBound(arr2arg) = 0 Then
    Set coll1 = Nothing
    coll1.Add arr2arg(0)
    VBtrip = arr2arg(0)
    Exit Function
End If
For i = 0 To UBound(arr2arg)
    If arr2arg(i) = "" And i = 0 Then
        GoTo prosegui
    ElseIf arr2arg(i) = "" And i <> UBound(arr2arg) Then
        coll1.Remove coll1.Count
    Else
        If arr2arg(i) <> "" Then coll1.Add arr2arg(i)
    End If
prosegui:
Next i
For Each elem In coll1
    stringa = "" & stringa & elem + "."
Next elem
stringa = Left(stringa, Len(stringa) - 1)
VBtrip = stringa
End Function
ciao,
Panathos

 "come l'ho inteso", dimmi un po' tu.
Stavo notando l' "intrippamento"
Quello che ho fatto e' questo
J:   private String getSezione(String sz, String ln){
A:   Function getSezione(sz as string, ln as string)
      Dim sezione as string, newsez as string, aSez as variant, ix as 
long, i as long
J:      String sezione = ln.replaceAll("\\]|\\[", "").trim();
A:      sezione = replace(replace(trim(ln),"[",""),"]","")
J:      if(!sezione.substring(0,1).equals(".")) {return sezione+".";}
A:      if left(sezione,1)<>"." then
		getsezione = sezione & "."
		exit function
	end if
J:      String newSez = sezione.replaceAll("^\\.+","");
A:      for i=1 to len(newsez)
	    if mid(newsez,i,1) <> "." then exit for
         next
         newsez = mid(newsez,i)
J:      String[] aSez = sz.split("\\.");
A:	asez = split(sz,".")
j:      int ix=aSez.length;
         ix-=(newSez.equals("")?0:-1)+(sezione.length()-newSez.length());
A:      ix=ubound(asez) - (iif(newsez="",0,-1)) + (len(sezione)-len(newSez))
J/A:     sezione = "";
J:       for(int i=0;i<ix;i++){
             sezione += aSez[i] + ".";
         }
A:     for i=0 to ix-1
	 sezione = sezione & aSez(i) & "."
        next
J:     return sezione+newSez+(newSez.equals("")?"":".");
A:	getSezione = sezione & newSez & iif(newSez="","",".")
     }
La roba access l'ho  tradotta in corsa. Potrebbe dare un errore sulla: 
newsez = mid(newsez,i) len caso di punti da soli.
A occhio il J: va bene pure per c# e tolte le definizioni del tipo anche 
per Javascript
E' che volevo fare una routine senza cicli ma credo sia difficile.
Ora poi mi guardo il tuo codice.
--
ac

 Ora poi mi guardo il tuo codice.
Per funzionare, funziona. Però continuo a pensare che se VBA fosse un
tantino più sviluppato.... ma chiudo per non tornare sui discorsi di
qualche tempo fa :-)
ciao,
Panathos

 qualche tempo fa :-)
Davo per scontato che funzionasse.
Ti "voglio" fare solo un appunto. La GoTo, anche se credo di aver capito 
la ragione.
VBA e' sviluppato. Il suo limite e' che, essendo un prodotto "di 
proprieta", non correda con tutti quegli "addin" previsti da php (o java 
stesso) che, alcune volte, piu' che addin sono "casin". Fare una 
libreria (mda) di possibili utility e' possibile anche per il VBA. Se 
non ci sono e se non c'e' una vasta "community" che lavori in tal senso, 
secondo me, e' dovuto al fatto che il 90% della roba che veramente serve 
gia' c'e' ed, inoltre, il mondo che gira intorno ad access e' formato 
solo per il 20% di gente con capacita' di intendere e volere.
Se qualcuno si sente dalla parte dell'80% non si adombri non voleva 
essere offensivo, e' il prodotto stesso che consente di fare pur  non 
sapendo.
--
ac

 sapendo.
Figura nella quale mi riconosco appieno, dopotutto. Per quanto mi
impegni, sono sempre più le cose che non conosco rispetto a quelle che
riesco ad imparare.
ciao,
Panathos