login  Naam:   Wachtwoord: 
Registreer je!
 Forum

String.Replace(Array(), Array())

Offline Ontani - 05/02/2010 13:55
Avatar van OntaniGouden medailleGouden medailleGouden medailleGouden medaille

-1
Eentje om uw brein op te breken.

Ik wil de String.Replace functie extenden. .NET heeft geen replace functie voor string array's zoals php dat kan.

Toch komt dit wel eens van pas.

Veel doen dan in .NET:

  1. Dim strTest as String = "ABCDEFG"
  2. MsgBox(strTest.Replace(“A”,”B”).Replace(“B”, “C”).Replace(“C”, “D”).Replace(“D”, “E”).Replace(“E”, “F”).Replace(“F”, “G”).Replace(“G”, “A”))


Maar dit geeft eigenlijk niet het resultaat wat je wil.

Je wil eigenlijk A vervangen door B en B door C en C door D enz.
Niet dat A vervangen wordt door B en dat op z'n beurt dan door C en dan weer naar D.

Want het resultaat van deze MessageBox zal "AAAAAAA" zijn.

Ik wil dus het volgende bereiken:

  1. Dim strTest as String = “ABCDEFG”
  2. MsgBox(strTest.Replace( _
  3. new Object() { “A”, “B”, “C”, “D”, “E”, “F”, “G” }, _
  4. new Object() { “B”, “C”, “D”, “E”, “F”, “G”, “A” } _
  5. )


Met als uitkomst : "BCDEFGA"

Hoe zouden jullie hier aan beginnen?

Ik heb al een mogelijk oplossing maar ben er niet 100% tevreden over: http://pastebin.be/23290

Alle ideeën zijn welkom.

het is moeilijker als je initieel denkt

11 antwoorden

Gesponsorde links
Offline Abbas - 05/02/2010 17:53
Avatar van Abbas Gouden medaille

Crew .NET
Ik heb even iets geprobeerd dat jouw voorbeeld wel doet werken. Als het niet is wat je bedoelt heb ik je verkeerd begrepen of snap ik het niet..  

Extension Module
  1. Module Extension
  2. <System.Runtime.CompilerServices.Extension()> _
  3. Public Function Replace(ByVal input As String, ByVal oldValues As String(), ByVal newValues As String()) As String
  4.  
  5. Dim inputChars As String() = GetStringArray(input)
  6. Dim i As Integer = 0
  7. For Each s As String In inputChars
  8. If oldValues.Contains(s) Then
  9. inputChars(i) = newValues(System.Array.IndexOf(oldValues, s))
  10. End If
  11. i = i + 1
  12. Next
  13. Dim strReturn As String = String.Empty
  14. For Each s As String In inputChars
  15. strReturn &= s
  16. Next
  17. Return strReturn
  18.  
  19. End Function
  20.  
  21. Public Function GetStringArray(ByVal input As String) As String()
  22. Dim lstChars As New List(Of String)
  23. For Each c As Char In input.ToCharArray()
  24. lstChars.Add(c.ToString())
  25. Next
  26. Return lstChars.ToArray()
  27. End Function
  28. End Module

Aanroep
  1. Sub Main()
  2. Dim input As String = "ABCDEFG"
  3. Dim newString As String = input.Replace(New String() {"X", "B", "C", "D", "E", "F", "G"}, New String() {"B", "C", "D", "E", "F", "G", "A"})
  4. Console.WriteLine(newString)
  5. Console.ReadLine()
  6. End Sub
Offline Ontani - 06/02/2010 13:44
Avatar van Ontani Gouden medailleGouden medailleGouden medailleGouden medaille

-1
Dit zal deels werken.

Maar voor bijvoorbeeld:

  1. Sub Main()
  2. Dim input As String = "ABCfooDEFG"
  3. Dim newString As String = input.Replace(New String() {"X", "B", "C", "D", "E", "F", "G", "foo"}, New String() {"B", "C", "D", "E", "F", "G", "A", "bar"})
  4. Console.WriteLine(newString)
  5. Console.ReadLine()
  6. End Sub


Gaat ge nie krijgen: BCDbarEFGA
maar: BCDGooEFGA
Offline Abbas - 06/02/2010 18:28 (laatste wijziging 06/02/2010 18:34)
Avatar van Abbas Gouden medaille

Crew .NET
I found it (I guess)  Ik heb het getest met een aantal voorbeelden. Hetgeen jij als eerste gaf en ook met die 'foo' erin. Ook met een string waar er meerdere keren een te vervangen waarde wordt gevonden en dit werkt. 

  1. Imports System.Linq
  2.  
  3. Module Extension
  4.  
  5. <System.Runtime.CompilerServices.Extension()> _
  6. Public Function Replace(ByVal input As String, ByVal oldValues As String(), ByVal newValues As String()) As String
  7.  
  8. Dim charDictionary As New SortedDictionary(Of Integer, String)
  9. Dim i As Integer = 0
  10. For Each s As String In oldValues
  11. Dim start As Integer = 0
  12. While input.IndexOf(s, start) > -1
  13. charDictionary.Add(input.IndexOf(s, start), newValues(System.Array.IndexOf(oldValues, s)))
  14. start = start + input.IndexOf(s, start) + s.Length
  15. End While
  16. Next
  17.  
  18. charDictionary = PrepareDictionary(charDictionary)
  19. Dim indexes As List(Of Integer) = GetUnusedIndexes(input.Length - 1, charDictionary.Keys)
  20. For Each index As Integer In indexes
  21. charDictionary.Add(index, input(index))
  22. Next
  23.  
  24. Dim returnString As String = String.Empty
  25. For Each key As Integer In charDictionary.Keys
  26. returnString &= charDictionary(key)
  27. Next
  28. Return returnString
  29.  
  30. End Function
  31.  
  32. Public Function GetUnusedIndexes(ByVal lastIndexOfInput As Integer, ByVal usedIndexes As SortedDictionary(Of Integer, String).KeyCollection) As List(Of Integer)
  33.  
  34. Dim lst As New List(Of Integer)
  35. Dim i As Integer
  36. For i = 0 To lastIndexOfInput
  37. If Not usedIndexes.Contains(i) Then
  38. lst.Add(i)
  39. End If
  40. Next
  41. Return lst
  42.  
  43. End Function
  44.  
  45. Public Function PrepareDictionary(ByVal dictionary As SortedDictionary(Of Integer, String)) As SortedDictionary(Of Integer, String)
  46.  
  47. Dim i As Integer
  48. Dim items = From k In dictionary.Values Select k
  49. Dim d As New SortedDictionary(Of Integer, String)
  50. For Each s As String In items.ToList()
  51. Dim index As Integer = (From k In dictionary Where String.Compare(k.Value, s, False).Equals(0) Select k.Key).FirstOrDefault()
  52. For i = 0 To s.Length - 1
  53. d.Add(index + i, s(i))
  54. Next
  55. dictionary.Remove(index)
  56. Next
  57. Return d
  58.  
  59. End Function
  60.  
  61. End Module
Offline Ontani - 06/02/2010 18:46
Avatar van Ontani Gouden medailleGouden medailleGouden medailleGouden medaille

-1
Dit lijkt me helemaal niets te doen. Raar genoeg kan de debugger er zelfs niet doorheen lopen, stopt gewoon in het midden van de Replace functie
Offline Abbas - 06/02/2010 19:16 (laatste wijziging 06/02/2010 19:29)
Avatar van Abbas Gouden medaille

Crew .NET
Het projectje want bij mij werkt het perfect! 

Edit:
Regel 9 mag weg. (Dim i As Integer = 0)
Offline Ontani - 06/02/2010 19:41
Avatar van Ontani Gouden medailleGouden medailleGouden medailleGouden medaille

-1
Bijna Het moet natuurlijk ook mogelijk zijn om "foo" te vervangen door "vervangstring". Een groter probleem omdat je dan met een onbekend aantal karakters zit te kloten.
Offline Abbas - 06/02/2010 19:57 (laatste wijziging 08/02/2010 21:31)
Avatar van Abbas Gouden medaille

Crew .NET
Hm, dan is het in de PrepareDictionary bij de Add() nog de juiste index zien te bepalen. Ik zal er nog eens naar kijken. 

Edit:
Ik heb er nog eens naar gekeken en normaal moet het nu werken, hoop ik! 

  1. Imports System.Linq
  2.  
  3. Module Extension
  4. <System.Runtime.CompilerServices.Extension()> _
  5. Public Function Replace(ByVal input As String, ByVal oldValues As String(), ByVal newValues As String()) As String
  6.  
  7. Dim charDictionary As New SortedDictionary(Of Integer, KeyValuePair(Of String, String))
  8. For Each s As String In oldValues
  9. Dim start As Integer = 0
  10. While input.IndexOf(s, start) > -1
  11. charDictionary.Add(input.IndexOf(s, start), New KeyValuePair(Of String, String)(s, newValues(System.Array.IndexOf(oldValues, s))))
  12. start = start + input.IndexOf(s, start) + s.Length
  13. End While
  14. Next
  15.  
  16. Dim indexes As List(Of Integer) = GetUnusedIndexes(input.Length - 1, charDictionary)
  17. For Each index As Integer In indexes
  18. charDictionary.Add(index, New KeyValuePair(Of String, String)(input(index), input(index)))
  19. Next
  20.  
  21. Dim finalDictionary As SortedDictionary(Of Integer, String) = PrepareDictionary(charDictionary)
  22.  
  23. Dim returnString As String = String.Empty
  24. For Each key As Integer In finalDictionary.Keys
  25. returnString &= finalDictionary(key)
  26. Next
  27. Return returnString
  28.  
  29. End Function
  30.  
  31. Public Function GetUnusedIndexes(ByVal lastIndexOfInput As Integer, ByVal usedIndexes As SortedDictionary(Of Integer, KeyValuePair(Of String, String))) As List(Of Integer)
  32.  
  33. Dim lstUnused As New List(Of Integer)
  34. For i As Integer = 0 To lastIndexOfInput
  35. lstUnused.Add(i)
  36. Next
  37. For Each kvp As KeyValuePair(Of Integer, KeyValuePair(Of String, String)) In usedIndexes
  38. For k As Integer = kvp.Key To (kvp.Key + kvp.Value.Key.Length) - 1 Step 1
  39. lstUnused.Remove(k)
  40. Next
  41. Next
  42. Return lstUnused
  43.  
  44. End Function
  45.  
  46. Public Function PrepareDictionary(ByVal dictionary As SortedDictionary(Of Integer, KeyValuePair(Of String, String))) As SortedDictionary(Of Integer, String)
  47.  
  48. Dim d As New SortedDictionary(Of Integer, String)
  49. For Each kvp As KeyValuePair(Of String, String) In (From v In dictionary.Values Select v).ToList()
  50. Dim index As Integer = (From k In dictionary Where String.Compare(k.Value.Value, kvp.Value, False).Equals(0) Select k.Key).FirstOrDefault()
  51. If (d.ContainsKey(index)) Then
  52. index = d.Last().Key + 1
  53. End If
  54. For i As Integer = 0 To kvp.Value.Length - 1
  55. d.Add(index + i, CStr(kvp.Value()(i)))
  56. Next
  57. Next
  58. Return d
  59.  
  60. End Function
  61.  
  62. End Module

Volgende test werkt in ieder geval:

  1. input = "ABCfooDEFG"
  2. newString = input.Replace(New String() {"A", "B", "C", "D", "E", "F", "G", "foo"}, New String() {"B", "C", "D", "E", "F", "G", "A", "blaat"})
  3. Console.WriteLine(newString)

Ook als je dan bijvoorbeeld "foo" door "X" vervangt (vervangwaarde < te vervangen waarde) werkt het. 

Edit2:
Vervang regel 12 eens door het volgende:

  1. start = input.IndexOf(s, start) + s.Length

Klein foutje dat er nog in zat! 
Offline Ontani - 08/02/2010 21:34
Avatar van Ontani Gouden medailleGouden medailleGouden medailleGouden medaille

-1
Belachelijk lastige oplossing voor iets wat zo simpel lijkt hé Kwam hier tot diezelfde conclusie.
Offline Abbas - 08/02/2010 21:52
Avatar van Abbas Gouden medaille

Crew .NET
Inderdaad, ik heb het wel nog een stuk kunnen inkorten. Er was een stuk code dat eigenlijk werk voor niets was. Nu is het toch meer dan 10 regels korter en werkt evengoed! 

  1. Imports System.Linq
  2.  
  3. Module Extension
  4. <System.Runtime.CompilerServices.Extension()> _
  5. Public Function Replace(ByVal input As String, ByVal oldValues As String(), ByVal newValues As String()) As String
  6.  
  7. Dim charDictionary As New SortedDictionary(Of Integer, KeyValuePair(Of String, String))
  8. For Each s As String In oldValues
  9. Dim start As Integer = 0
  10. While input.IndexOf(s, start) > -1
  11. charDictionary.Add(input.IndexOf(s, start), New KeyValuePair(Of String, String)(s, newValues(System.Array.IndexOf(oldValues, s))))
  12. start = input.IndexOf(s, start) + s.Length
  13. End While
  14. Next
  15.  
  16. For Each index As Integer In GetUnusedIndexes(input.Length - 1, charDictionary)
  17. charDictionary.Add(index, New KeyValuePair(Of String, String)(input(index), input(index)))
  18. Next
  19.  
  20. Return PrepareDictionary(charDictionary)
  21.  
  22. End Function
  23.  
  24. Public Function GetUnusedIndexes(ByVal lastIndexOfInput As Integer, ByVal usedIndexes As SortedDictionary(Of Integer, KeyValuePair(Of String, String))) As List(Of Integer)
  25.  
  26. Dim lstUnused As New List(Of Integer)
  27. For i As Integer = 0 To lastIndexOfInput
  28. lstUnused.Add(i)
  29. Next
  30. For Each kvp As KeyValuePair(Of Integer, KeyValuePair(Of String, String)) In usedIndexes
  31. For k As Integer = kvp.Key To (kvp.Key + kvp.Value.Key.Length) - 1 Step 1
  32. lstUnused.Remove(k)
  33. Next
  34. Next
  35. Return lstUnused
  36.  
  37. End Function
  38.  
  39. Public Function PrepareDictionary(ByVal dictionary As SortedDictionary(Of Integer, KeyValuePair(Of String, String))) As String
  40.  
  41. Dim returnString As String = String.Empty
  42. For Each kvp As KeyValuePair(Of String, String) In (From v In dictionary.Values Select v).ToList()
  43. returnString &= kvp.Value
  44. Next
  45. Return returnString
  46.  
  47. End Function
  48.  
  49. End Module
Offline Ontani - 09/02/2010 08:24
Avatar van Ontani Gouden medailleGouden medailleGouden medailleGouden medaille

-1
Het werkt eigenlijk nog niet volledig, probeer maar eens:
  1. Dim test As String = "ABCFooCDE12ABC3456BCD"
  2. MsgBox(test.Replace( _
  3. New String() {"12", "E1", "F", "ABC", "Foo", "C", "5", "23"}, _
  4. New String() {"00", "@6", "G", "BCD1", "Bar", "X", "C", "01"}))
Offline Abbas - 09/02/2010 10:55
Avatar van Abbas Gouden medaille

Crew .NET
Grrr! En echt altijd een foutje vinden e..  Ik fix da nog wel! 
Gesponsorde links
Dit onderwerp is gesloten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.23s