Loop over strings added to StringBuilder
Asked Answered
B

6

5

I have the following code:

StringBuilder sb = new StringBuilder();
sb.Append("Ola");
sb.Append("Jola");
sb.Append("Zosia");

Can I iterate over StringBuilder object using for, or foreach?

Can I display one element of it? For example Console.WriteLine(sb[0]); doesn't work.

Basilica answered 1/7, 2015 at 10:42 Comment(7)
It really sounds like a StringBuilder is the wrong object that you should be using, what are you trying to do?Operation
This seems to be a classical XY problem, where X is your original problem and your perceived solution was "I know, I'll use StringBuilder", causing you to have the problem Y: "But now I can't get separate strings back from the StringBuilder". Explain your original problem X.Numismatist
A possibility is to store each Append with a separator <space> (may be). and split with Split(separator) and show elements[0] where elements is the array of splits.Vicar
@Vicar no, simply accept you have the wrong data structure for your problem. Don't go implement hacks like that.Numismatist
@CodeCaster, you didn't noticed i said a possibility. Glad to see you have another.Vicar
@Vicar yes, it is a possibility, like there are many. It's not an option that makes much sense though. For example because it goes wrong if one of the inputs contains the separator value. So you'll be writing broken code and a lot of code to support it, as opposed to simply properly describing the problem and choosing the sensible approach.Numismatist
@CodeCaster, It really depends on what OP is trying to achieve ? Code may break, but depends on the allowed input string. we can't decide here without going into details. You suggested List<> option but may be OP would like to stick with StringBuilder for no reason. One has the right to provide alternatives which may/may not be buggy for others.Vicar
N
4

You seem to be looking for a List<string>, to which you can Add() strings that you can later get by index (list[n]) and iterate over (foreach (string s in list)).

StringBuilder doesn't support this, as it concatenates all input internally and can't distinguish between values of different Append() calls afterwards.

To get a concatenated string from a list of strings, see Append List items to StringBuilder.

Numismatist answered 1/7, 2015 at 10:43 Comment(0)
K
3

StringBuilder doesn't implement IEnumerable, so you can't foreach over it, but you can do something like this:

StringBuilder sb = new StringBuilder();
sb.Append("Ola");
sb.Append("Jola");
sb.Append("Zosia");

for (int i = 0; i < sb.Length; i++)
{
    char c = sb[i];
    if (Char.IsUpper(c)) Console.Write('\n');
    Console.Write(c);
}
Keeshakeeshond answered 1/7, 2015 at 10:53 Comment(2)
if (Char.IsUpper(c)) Console.Write('\n'); ... no, no. This assumes that the input always starts with an uppercase character and doesn't contain any other uppercase characters. OP should use a different data structure or at least explain their problem properly.Numismatist
@Numismatist I know, but here OP is just adding names always starting with uppercase letters, so it just works in this case if OP insists on iterating a StringBuilderKeeshakeeshond
M
1

StringBuilder is not a collection or array. It's just a class that provides some extra features to work with string. It doesn't implement IEnumerable interface.

sb.Append method just concatenates strings like you do if you type "text " + "some other text" but in a much better way in terms of efficiency. In fact every "s1" + "s2" results in creating of new string. If you want to do it like 1000 times so it creates new string again and again with a lot of extra operations to do. StringBuilder provides a way to avoid it, when it 'renders' string it updates the same string instead of creating new istance every time.

Marjie answered 1/7, 2015 at 10:46 Comment(0)
M
0

If you really want to stick with a StringBuilder you can use an extension method to give you a List and then you can access it with an element number.

internal static class ExtensionMethods
{
    public static List<string> ToList(this StringBuilder stringBuilder)
    {
        return stringBuilder.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList();
    }
}

You can then access it by calling the ToList() method.

int i = 0;
StringBuilder SB = new StringBuilder();
while (i++ != 1000000)
{
    SB.AppendLine(i.ToString());
}

string ChosenElement = SB.ToList()[1000];
Monticule answered 1/7, 2015 at 11:4 Comment(2)
This assumes the input strings never contain a newline. Use a StringBuilder to build strings, use a List<T> to store items you want to look up on index and that you want to iterate over.Numismatist
@Numismatist Yes it does but its the closest you can get without initially using a List.Monticule
M
0

I know its too late to answer this question, but i hope someone else get help from this.

 public static void Main(string[] args)
    {

        StringBuilder sb = new StringBuilder("1");
        for(int i=2; i<= 300; i++){
                sb.Append(i+" this is test.~");
        }
        foreach(string s in sb.ToString().Split('~')){
        Console.WriteLine(s);
        }
    }

EDIT: in your example:

 StringBuilder sb = new StringBuilder();
     sb.Append("Ola~");
     sb.Append("Jola~");  
     sb.Append("Zosia~");

 //foreach loop ver sb object

  foreach(string s in sb.ToString().Split('~')){
         Console.WriteLine(s);
          }
Masseuse answered 11/2, 2018 at 4:51 Comment(2)
its not too late- just write an explanation of what you did.Shake
i just add a special character to the string at the end ~ 'sb.append();' and then split the string over that character. You can add your own token and then split the stringbuilder object with that token in foreach loop.Masseuse
S
0

I was able to get a workable solution for a very similar scenario by using this post as a guideline:

Replace Line Breaks in a String C#

If you are able to use sb.AppendLine instead you could split the resulting ToString() via the newline characters '\r' and '\n'

// e.g whereas you had:
StringBuilder sb = new StringBuilder();
sb.Append("Ola");
sb.Append("Jola");
sb.Append("Zosia");

// the scenario will only work if you did the following:
StringBuilder sb = new StringBuilder();
sb.AppendLine("Ola");
sb.AppendLine("Jola");
sb.AppendLine("Zosia");

// you can split your strings as follows:
string[] resultLines = TestResultStr.ToString().Split(new char[] { '\n', '\r' });

for (int i = 0; i < resultLines.Length; i++)
{
    Console.WriteLine(resultLines[i]);
}
Scram answered 23/5, 2019 at 22:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.