Как я могу изменить строки, используя цикл «Для каждого»? - PullRequest
5 голосов
/ 21 июля 2010
       '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

Если string1 содержит "foo", я предполагаю, что string1 содержит "-foo-" после выполнения цикла. Как я могу сделать эту работу?

Я предполагаю, что этот код делает копии моих строк и модифицирует их. Как я могу изменить мои строки в цикле?

Обновление Я изменил код для использования индексов массива:

    ' 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

Результат этого кода, относящийся конкретно к массиву и индексу для каждого элемента, модифицирует массив, но мои строки по-прежнему имеют те же старые значения. По-видимому, инициализация такого массива просто копирует мои значения в новый массив. Как я могу изменить мои исходные значения в цикле?

Акцент: Массив только для циклических целей. Мне нужно изменить string1, string2 и string3 аналогичным образом, но как только этот цикл закончится, массив больше не будет использоваться. О, и мой реальный код содержит более 3 строк.

Позвольте мне просто сказать, что если бы я использовал язык с большим количеством указателей и ссылок, я думаю, я бы просто имел массив указателей, которые указывают на string1, string2, and string3`. Кажется излишним копировать эти строки в массив.

Ответы [ 10 ]

5 голосов
/ 21 июля 2010

Этот пример написан на C #, но применяется тот же принцип.

string[] myStrings = new string[] { "temp", "temp2", "temp3" };
myStrings = myStrings.Select(x => "-" + x + "-").ToArray();

Выход:

"- temp-" "-temp2-" "-temp3 -"

Ссылка на статью MSDN: http://msdn.microsoft.com/en-us/library/bb548891.aspx

Вы также можете использовать функцию делегата, чтобы проверить, является ли строка пустой. Будет работать над предоставлением решения VB и редактировать, когда я его получу

РЕДАКТИРОВАТЬ:

Dim myStrings As String() = _
        {"apple", "banana", "mango", Nothing, "passionfruit", "grape"}
    myStrings = _
        myStrings.Select(Function(fruit) ("-" & fruit & "-")).ToArray()

Выход:

"- apple-" "-banana-" "-mango-" "-" "-passionfruit-" "-grape -"

РЕДАКТИРОВАТЬ 2: Делает то же самое, что и первое редактирование, но более читабельно

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
3 голосов
/ 21 июля 2010

Используйте For / Next и, в конце, myStrings(i) = s, чтобы сохранить результат.

2 голосов
/ 21 июля 2010

В зависимости от характера вашей коллекции вы можете хранить в ней массивы единой длины, а не строки.Если вы это сделаете, вы сможете изменить 0-й элемент каждого массива для его обновления.

Например, вы можете иметь словарь (Of String, String ()), который отображает строки в строковые массивы,Если в словаре хранятся одноэлементные массивы, вы можете легко изменить 0-й элемент любого из них, не нарушая словарь.Обратите внимание, что вы не должны делать это со словарем keys , так как словарь не сможет выполнять поиск на основе содержимого строк.

Кстати, я иногда хотел получитькласс коллекции, чей перечислитель будет возвращать объект, который можно использовать для запроса изменения коллекции без сглаживания перечисления.Не уверен, как управлять такой вещью, не кодируя коллекцию с нуля.

2 голосов
/ 21 июля 2010

Учитывая ваше последнее обновление, то, что вы спрашиваете, невозможно.

Строки следуют семантике значений, поэтому все, что вы делаете со строкой в ​​массиве, не влияет на исходную строку.Самое близкое, что вы можете найти к указанной строке - это StringBuilder, но ее не так просто использовать по своему усмотрению.

Вам нужно сделать шаг назад и спросить себя, почему вы пытаетесь это сделатьвсе так;другими словами, какова ваша настоящая цель.Как только вы поделитесь этим, возможно, мы сможем найти решение, которое работает.

2 голосов
/ 21 июля 2010

Это не работает, потому что строки неизменны в .Net - вы не можете изменить значение string1 без явной установки string1 на какое-либо значение, то есть, выполнив:

string1 = "Blah";

(Обратите внимание, что вы можете изменить значение i-го строкового значения в массиве myString, используя (например) for вместо foreach, однако из того, что я понял, это не то, что вам нужно делать)

Чтобы решить вашу проблему, вам нужно дать лучшее представление о том, какую проблему вы пытаетесь решить, например, вы можете избежать необходимости изменять ссылки на строки таким способом, настраивая свой интерфейс (см. this вопрос для вдохновения)

1 голос
/ 21 июля 2010

Это будет легко заключено в ParamArray из ByRef параметров, но это не вариант
: - (

Итак, вам, кажется, придется сделать это вручную:

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

РЕДАКТИРОВАТЬ: обратите внимание, что проще сделать что-то вроде этого (он просто не дает ничего похожего на то, что задает вопрос):

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
1 голос
/ 21 июля 2010

После вашего редактирования я не думаю, что вы можете сделать это так, как вы хотите.Я думаю, что вам лучше скопировать ваши строки в массив и работать с массивом.Вместо строки1, строки2 и т. Д. У вас будет массив [0], массив [1] и т. Д. *

Что-нибудь мешает вам сделать это?

1 голос
/ 21 июля 2010

Это не работает, потому что строки неизменны.

Попробуйте вместо этого.

For x As Integer = 0 To myStrings.Length - 1
   myStrings(x) = "new string"
Next

Редактировать после обновления.

Я не уверен, что это возможно.

Может быть, вы могли бы просто написать функцию?

string1 = MyFunction (string1)

1 голос
/ 21 июля 2010

Переменные итерации неизменны.Либо используйте «классический» цикл, либо другой массив для хранения ваших строк.

0 голосов
/ 28 августа 2012

Как предлагается в комментарии @ Джастина, альтернативой является использование Dictionary и VB's With и ! синтаксиса.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...