11.886 messaggi dal 09 febbraio 2002
Contributi
ciao Pietro,
potresti scriverti un extension method, così il codice resterà leggibile quando ne concateni molti di seguito.

Non è complicato: come ti ha segnalato Domenico, devi solo aggiungere una sequenza \r\n opzionale dopo ogni carattere del campo.

Ecco un extension method di esempio:
Public Module Estensioni
    <Extension()> 
    Public Function SostituisciCampo(ByVal testo As String, ByVal campo As String, ByVal valore as Object) As String
        If String.IsNullOrWhiteSpace(campo) Then Return testo
        
        'Aggiungo le parentesi quadre
        Dim espressione As String = "[" & campo & "]"
        'Come indicato da Domenico, aggiungo un ritorno a capo dopo ogni carattere
        'Uso un'espressione regolare per farlo
        Dim ogniCarattere = New Regex("(.)")
        espressione = ogniCarattere.Replace(espressione, "$1\r?\n?")
        'Le parentesi quadre devono avere l'escape per essere trattate letteralmente
        espressione = espressione.Replace("[", "\[").Replace("]", "\]")

        'Adesso eseguo la sostituzione vera e propria
        Return New Regex(espressione).Replace(testo, valore.ToString())
        
    End Function
End Module

Si usa così:
Dim risultato As String = testoRtf _
            .SostituisciCampo("nome_field", "Mario") _
            .SostituisciCampo("eta_field", 44) _
            .SostituisciCampo("data_field", DateTime.Now)

Se fai delle modifiche puoi anche ridurre le chiamate al metodo. Ad esempio, usando i tipi anonimi e la reflection, potresti ridurre tutto ad una sola chiamata.
Dim risultato As String = testoRtf.SostituisciCampi(New With {
   .nome_field = "Mario",
   .eta_field = 44,
   .data_field = DateTime.Now
})


ciao,
Moreno
Modificato da BrightSoul il 26 aprile 2014 10.40 -

Enjoy learning and just keep making
3.939 messaggi dal 28 gennaio 2003
Ringrazio per i consigli e l'ottimo codice.
Ciao
3.939 messaggi dal 28 gennaio 2003
 Non so se abuso. I vostri suggerimenti di sopra producono un codice perfettamente funzionante.
Per ragioni didattiche vorrei risolvere il problema anche senza le espressioni regolari e questo proprio per apprezzare di più la soluzione da voi proposta.
Ciao
11.886 messaggi dal 09 febbraio 2002
Contributi
pietro09 ha scritto:

risolvere il problema anche senza le espressioni regolari

Ah, questo si presta benissimo come kata, prova a farlo per esercitarti. Crea un progetto console ed aggiungici anche un progetto per lo unit testing, così potrai sperimentare il Test driven development. Procedi per piccoli passi, le regole da testare e implementare in ordine sono queste:
  • Data una stringa contenente un campo [nome] (cioè una sequenza di caratteri tra parentesi quadre), una funzione dovrà dare in output una stringa in cui il campo è stato sostituito da un valore. Alla funzione verrà fornito sia il nome di tale campo (privo di parentesi quadre) che il relativo valore.
  • Solo i nomi circondati da parentesi quadre (es. "[nome]") dovranno essere sostituiti. Altre occorrenze prive di parentesi quadre (es. "nome") dovranno restare inalterate
  • La sostituzione deve essere operata in maniera case-insensitive
  • La sostituzione deve avvenire anche se il campo, parentesi quadre comprese, contiene degli a capo.
  • Nella stringa di input sono consentite più occorrenze dello stesso campo, e tutte vanno rimpiazzate con il relativo valore.
  • Nella stringa possono essere presenti più campi dal nome diverso, e tutti vanno sostituiti con il rispettivo valore.
  • I campi per cui non viene fornito un valore, devono restare inalterati
  • Se non viene fornito alcuni valore da sostituire, la stringa in output sarà identica all'input
  • Eventuali valori Nothing saranno interpretati come stringa vuota
  • Eventuali sequenze di caratteri inattese nella stringa di input (come [[nome]], [nome, []nome], [no[me]) non devono produrre errori

Ricorda che nel TDD prima si scrive il test, lo si guarda fallire e poi si scrive il codice minimo che serve a farlo passare.
Come con tutti gli altri kata, non è tanto importante quello che si realizza ma l'esperienza in sé che ti porta alla soluzione.

I dettagli implementativi non hanno molta importanza, ma se vuoi comunque vedere il codice domani te lo posto.
Intanto ti linko i miei unit tests, se volessi avere una traccia.
http://pastebin.com/RatUQMXt

ciao,
Moreno
Modificato da BrightSoul il 30 aprile 2014 08.11 -

Enjoy learning and just keep making
3.939 messaggi dal 28 gennaio 2003
Quella di sotto è la procedura che ho scritto, confrontato con quello ben più compatto che fa uso delle espressioni regolari.
Anche se sembra funzionare non mi convince troppo.



'------------------------------------------------------------------------------------------------------
'sostituisce tutte le ricorrenze di campo in testo, con valore
'campo deve iniziare con [ e terminare con ], per esempio [c_nome]
'all'interno di campo ci possono essere \r\n
'------------------------------------------------------------------------------------------------------
<System.Runtime.CompilerServices.Extension()>
Public Function SostituisciCampo(testo As String, campo As String, valore As String) As String
  Dim sb As New StringBuilder(36)
  Dim sb1 As New StringBuilder(36)
  Dim index As Integer = -1
  Dim p As Integer = index
  Do
    index = testo.IndexOf("["c, index + 1)
    If Not (index >= 0 AndAlso index < (testo.Length - 1)) Then
      Exit Do
    End If

    p = testo.IndexOf("]"c, index + 1)
    sb.Clear() : sb1.Clear()
    For i As Integer = index To p
      Dim c As Char = testo.Chars(i)
      sb.Append(c)
      If Not Char.IsControl(c) Then sb1.Append(c)
    Next
    If sb1.ToString = campo Then
      testo = testo.Replace(sb.ToString, valore)
    End If
  Loop Until index < 0
  Return testo
End Function

'---------------------------------------------------------------------------------------------
'stessa di prima ma con le espressioni regolari
'---------------------------------------------------------------------------------------------
<System.Runtime.CompilerServices.Extension()>
Public Function SostituisciCampoX(testo As String, campo As String, valore As String) As String
  Dim ogniCarattere As New Regex("(.)")
  campo = ogniCarattere.Replace(campo, "$1\r?\n?")
  campo = campo.Replace("[", "\[").Replace("]", "\]")
  Return New Regex(campo).Replace(testo, valore)

End Function
11.886 messaggi dal 09 febbraio 2002
Contributi
Sì, anche a me sembra che funzioni, infatti passa tutti gli unit tests tranne quello (marginale) delle sostituzioni case-insensitive.

pietro09 ha scritto:

Anche se sembra funzionare non mi convince troppo.

Beh, l'altra soluzione è da preferire perché sfrutta le espressioni regolari: uno strumento potente che ti consente di realizzare sostituzioni complesse in poco tempo. Per non parlare della leggibilità e sinteticità del codice.

Sono davvero pochissimi i casi in cui non conviene usare un'espressione regolare, come per esempio quando vuoi la massima efficienza dalla tua applicazione, perché magari il suo lavoro è proprio quello di produrre il maggior numero di sostituzioni per secondo. Sotto questa prospettiva, l'ultima procedura che hai scritto è la migliore perché più veloce di 5-6 volte rispetto a quella basata su espressioni regolari.

ciao,
Moreno

Enjoy learning and just keep making
3.939 messaggi dal 28 gennaio 2003
Ah! sono contento che la tua risposta mi tolga molti dubbi.

Ti ringrazio ancora. Ciao.

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.