How can I modify strings using a "For Each" loop?
'Why doesn't this work? Dim myStrings As String() = New String() {string1, string2, string3,} For Each s As String In myStrings If String.IsNullOrEmpty(s) Then s = "" End If s = "-" & s.Trim() & "-" Next
If string1
contains "foo"
, my intention is that string1
contains "-foo-"
after the loop executes. How can I make this work?
I'm guessing that this code makes copies of my strings and modifies those. How can I modify my strings in a loop?
Update I've modified the code to use array indexes:
' It still doesn't work. Dim myStrings As String() = New String() {string1, string2, string3} For i As Integer = 0 To myStrings.Count() - 1 If String.IsNullOrEmpty(myStringss(i)) Then myStringss(i) = "" End If myStrings(i) = "-" & myStrings(i) & "-" Next
The result of this code, referring specifically to the array and index for each element, modifies the array, but my strings still have the same old values. Apparently, initializing an array like this simply copies my values into a new array. How can I modify my original values in a loop?
Emphasis: The array is just for looping purposes. I need to modify string1
, string2
, and string3
similarly, but once this loop is thru, there is no more use for the array. Oh, and my real code has more than 3 strings.
Let me just say that if I were using a language with more pointers and references, I think I would simply have an array of pointers that poin开发者_如何学运维t to string1
, string2, and
string3`. It seems redundant to copy these strings into an array.
This example is in C# but the same principle applies.
string[] myStrings = new string[] { "temp", "temp2", "temp3" };
myStrings = myStrings.Select(x => "-" + x + "-").ToArray();
Output:
"-temp-" "-temp2-" "-temp3-"
Link to the MSDN article: http://msdn.microsoft.com/en-us/library/bb548891.aspx
You can also use a delegate function to check whether the string is empty. Will work on providing a VB solution and edit when I get it
EDIT:
Dim myStrings As String() = _
{"apple", "banana", "mango", Nothing, "passionfruit", "grape"}
myStrings = _
myStrings.Select(Function(fruit) ("-" & fruit & "-")).ToArray()
Output:
"-apple-" "-banana-" "-mango-" "--" "-passionfruit-" "-grape-"
EDIT 2: Does the same thing as the first edit but more readable
Private Function TESTER(ByVal fruit As String) As String
Return "-" & fruit & "-"
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim myStrings As String() = _
New String() {"apple", "banana", "mango", Nothing, "passionfruit", "grape"}
myStrings = _
myStrings.Select(AddressOf TESTER).ToArray()
End Sub
Use a For/Next and in the end, myStrings(i) = s
to save the result.
This doesn't work because strings are immutable in .Net - you can't change the value of string1
without explicitly setting string1
to some value, i.e. by doing:
string1 = "Blah";
(Note that you can change the value of the i
th string value in the myString array by (for example) using for
instead of foreach
, however from what I gather this isn't what you want to do)
To solve your problem you are going to need to given a better idea of what problem you are trying to solve, for example you could avoid the need to modify string references in this way by tweaking your interface (see this question for inspiration)
Given your most recent update, what you ask is not possible.
Strings follow value semantics, so anything you do to the string in the array has no effect on the original string. The closest you can come to a referenced string is StringBuilder
, but it's not particularly easy to use in the way you want.
You need to take a step back and ask yourself why you're trying to do things this way; in other words, what your actual goal is. Once you share that, perhaps we can find a solution that works.
Depending upon the nature of your collection, you could store unity-length arrays in it rather than strings. If you did that, you would then be able to change the 0th element of each array to update it.
For example, you could have a Dictionary(Of String, String()) which mapped strings onto string arrays. If single-item arrays were stored in the dictionary, you could easily alter the 0th item of any of them without disturbing the dictionary. Note that you should not do that with the dictionary keys, since the dictionary would not be able to search based upon the content of the strings.
BTW, I've sometimes wished for a collection class whose enumerator would return an object which could be used to request an alteration to the collection without jinxing the enumeration. Not sure how to manage such a thing without having to code the collection from scratch.
Iteration variables are immutable. Either use a "classic" loop or another array to store your strings.
It doesn't work because strings are immutable.
Try this instead.
For x As Integer = 0 To myStrings.Length - 1
myStrings(x) = "new string"
Next
Edit after the update.
I'm not sure it's possible to do this.
Maybe you could just write a function?
string1 = MyFunction(string1)
After your edit I don't think you can do this the way you want to. I think you're better off copying your strings to the array and working with the array. Instead of having string1, string2, etc ... you'd have array[0], array[1], etc ...
Is there anything preventing you from doing so ?
This would be easily encapsulated into a ParamArray
of ByRef
parameters, but that isn't an option
:-(
So you seem to have to do it manually:
Imports System.Runtime.CompilerServices
Module Module1
Sub Main()
Dim String1 = "foo"
Dim String2 = ""
Dim String3 As String = Nothing
Dim strings() = New StrongBox(Of String)() {New StrongBox(Of String)(String1), New StrongBox(Of String)(String2), New StrongBox(Of String)(String3)}
Modify(strings)
String1 = strings(0).Value
String2 = strings(1).Value
String3 = strings(2).Value
Console.WriteLine("'{0}' '{1}' '{2}'", String1, String2, If(String3, "NOTHING"))
Console.ReadLine()
End Sub
Sub Modify(ByVal ParamArray myStrings() As StrongBox(Of String))
For i As Integer = 0 To myStrings.Count() - 1
If String.IsNullOrEmpty(myStrings(i).Value) Then
myStrings(i).Value = ""
End If
myStrings(i).Value = "-" & myStrings(i).Value & "-"
Next
End Sub
End Module
EDIT: Note that it is simpler to do something like this (it just doesn't supply anything like what the question is asking for):
Module Module1
Sub Main()
Dim String1 = "foo"
Dim String2 = ""
Dim String3 As String = Nothing
Modify(String1)
Modify(String2)
Modify(String3)
Console.WriteLine("'{0}' '{1}' '{2}'", String1, String2, If(String3, "NOTHING"))
Console.ReadLine()
End Sub
Sub Modify(ByRef myString As String)
If String.IsNullOrEmpty(myString) Then
myString = ""
End If
myString = "-" & myString & "-"
End Sub
End Module
As suggested in @Justin's comment, an alternative is to use a Dictionary
and VB's With
and !
syntax.
Module Module1
Sub Main()
Dim strings As New Dictionary(Of String, String)
With strings
!String1 = "foo"
!String2 = ""
!String3 = Nothing
Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING"))
Modify(strings)
Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING"))
ModifySome(strings, "String1", "String2")
Console.WriteLine("'{0}' '{1}' '{2}'", !String1, !String2, If(!String3, "NOTHING"))
End With
Console.ReadLine()
End Sub
Sub Modify(ByVal myStrings As Dictionary(Of String, String))
ModifySome(myStrings, myStrings.Keys.ToArray)
End Sub
Sub ModifySome(ByVal myStrings As Dictionary(Of String, String), ByVal ParamArray someStrings() As String)
For Each s As String In someStrings
If String.IsNullOrEmpty(myStrings(s)) Then
myStrings(s) = ""
End If
myStrings(s) = "-" & myStrings(s) & "-"
Next
End Sub
End Module
精彩评论