views:

167

answers:

6

I need to often convert a "string block" (a string containing return characters, e.g. from a file or a TextBox) into List<string>.

What is a more elegant way of doing it than the ConvertBlockToLines method below?

using System;
using System.Collections.Generic;
using System.Linq;

namespace TestConvert9922
{
    class Program
    {
        static void Main(string[] args)
        {
            string testBlock = "line one" + Environment.NewLine +
                "line two" + Environment.NewLine +
                "line three" + Environment.NewLine +
                "line four" + Environment.NewLine +
                "line five";

            List<string> lines = StringHelpers.ConvertBlockToLines(testBlock);

            lines.ForEach(l => Console.WriteLine(l));
            Console.ReadLine();
        }
    }

    public static class StringHelpers
    {
        public static List<string> ConvertBlockToLines(this string block)
        {
            string fixedBlock = block.Replace(Environment.NewLine, "§");
            List<string> lines = fixedBlock.Split('§').ToList<string>();
            lines.ForEach(s => s = s.Trim());
            return lines;
        }

    }
}
+3  A: 

Have you tried splitting on newline/carriage return and using the IEnumerable ToList extension?

testBlock.Split( new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries )
         .ToList()

If you want to keep empty lines but may have both linefeed and carriage return.

textBlock.Replace( "\r\n", "\n" ).Replace( "\r", "\n" ).Split( '\n' ).ToList();
tvanfosson
I could but in most cases I need to keep any *real* empty lines that may be in the string block. The way I understand it, your suggestion would delete these as well.
Edward Tanguay
I've updated to reflect your issue.
tvanfosson
@tvanfosson: It doesn't appear that you have :)
Noon Silk
FWIW, I downvoted this. It's technically wrong (the best kind of wrong?) because it will split even if the data isn't a "newline" based on the OS' preference. I.e. if the data contains a single \r, but it's newline char is \n. (At least in the first code block, I find the second block too ugly to even look at :P
Noon Silk
@silky: The second code block in the answer will keep empty lines, no?
Seth Petry-Johnson
@tvanfosson: You're correct there, I assumed you'd just not do the 'RemoveEmptyEntries' and make it 'None'. Nevertheless, mistake on my part.
Noon Silk
@silky: You make a good point re: \n vs \r vs \r\n, but I don't think it deserves a downvote. The question doesn't state whether the text being processed was _generated on_ the same platform it's being _parsed on_. Thus, it's entirely possible that the "split on all possible newline markers" is appropriate in this case.
Seth Petry-Johnson
whatever. Heaven help you if the "string" is generated by a non-Windows system.
tvanfosson
@Seth: If it was appropriate (which is never is, anyway) it should've been included in the "Testcase" shown by the OP. Regardless, desired or not, the implementation show here is strictly "wrong". Nothing personal. Just explaining my downvote. I sense there is no point to further comments on this matter.
Noon Silk
+12  A: 
List<string> newStr = str.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToList();

This will keep consecutive newlines as empty strings (see StringSplitOptions)

thecoop
You don't need to pass `StrringSplitOptions.None` because that's the default behavior of Split().
Seth Petry-Johnson
@Seth: You're wrong, you must pass it, when sending in a `string[]`, (and not a `char[]`). In this case, it's possibly not obvious to you that Environment.NewLine is a `string[]`. So your comment helps to highlight that it is good to be verbose :)
Noon Silk
Noooo! I don't have exactly 5000 rep anymore! :(
thecoop
@silky: My bad, you're right. That's what I get for commenting in a hurry...
Seth Petry-Johnson
A: 

LINQ!

var linesEnum = testBlock.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).AsEnumerable();

List<string> lines = linesEnum.ToList();
masenkablast
+2  A: 

Hmm. You know that string now has a .Split() that takes a string[] array, right?

So ...

string[] lines = data.Split(
    new string[1]{ Environment.NewLine },
    StringSplitOptions.None
);
Noon Silk
And this gets into List<String> how?
DOK
@DOK: You'd have to be blind freddy to not see how to do that. Regardless, although the OP has titled the question that way, with careful review of the question, you will note that wasn't his real problem.
Noon Silk
+2  A: 

ou can use RegEx.Split to split directly using the Enviroment.NewLine.

public static List<string> ConvertBlockToLines(this string block)
{
   return Regex.Split(block, Environment.NewLine).ToList();
}
LnDCobra
This seems like an abuse of Regex.Split() to me. Why would you want to incur the overhead of regex parsing and matching when you're not actually using a regex? String.Split() is a better solution here.
Seth Petry-Johnson
+4  A: 

No need to convert to your special sign:

List<string> strings = str.Split(new string[] {Environment.NewLine}, StringSplitOptions.None).ToList();
strings.ForEach(s => s = s.Trim());
Carra