Finding linq solution to replace loop

I constantly come across such examples. In this case, I want to populate the stringbuilder with a new line for each FileInfo object in a previously loaded variable called files , which of course contains a bunch of FileInfo objects. For the first object, I want to add FIRST after the text, and then for everything else, I want to add NOTFIRST . To do this with forloop, I need to set up a counter, execute an if statement, and increment the counter.

I found out if linq is enough that its at my fingertip, but I know there must be an elegant LINQ solution.

            var mysb = new StringBuilder();
            var count = 0;
            string extra;
            foreach (System.IO.FileInfo fi in files)
            {
                var newLine = fi.Name;
                if (count == 0)
                    extra = "FIRST";
                else
                    extra= "NOTFIRST";
                count = count++;
                mysb.AppendLine(string.Format("({0} {1})", newLine, extra));
            }

      

+3


source to share


4 answers


You can use the Select overload that gives the current index: http://msdn.microsoft.com/pl-pl/library/bb534869(v=vs.110).aspx

I also don't like the mutating state when using linq, so I would use String.Join instead.



mysb.AppendLine(String.Join(Environment.NewLine,
    files.Select((fi, i) => String.Format(fi.Name, i == 0 ? "FIRST" : "NOTFIRST"))));

      

+2


source


Personally, I would ditch LINQ and stick with what you have, it's just simpler:

var mysb = new StringBuilder();
foreach (FileInfo fi in files)
{
    string extra = mysb.Length == 0 ? "FIRST" : "NOTFIRST";
    mysb.Append(fi.Name);
    mysb.AppendLine(extra);
}

      



(It's not clear to me why you are treating the filename as a valid format string ... of course, if it is indeed a valid format string, you can change my two calls to Append()

and AppendLine()

back to a single call with string.Format()

)

+7


source


As often happens, I ask questions here, I went with a hybrid of sentences:

            foreach (var fi in files)
            {
                var extra = (fi == files.First() ? "FIRST" : "NOTFIRST");
                sb.AppendLine(fi.Name + extra);
            }

      

I didn't want to check the length of the stringbuilder because I have other scenarios where extra quite often requires using the linq function.

I suppose I could just as easily do the following (for my stated example):

            sb.AppendLine(files.First().Name + " FIRST");
            sb.AppendLine(String.Join(Environment.NewLine,
            files.Skip(1).Select( fi => fi.Name + " NOTFIRST")));

      

But to be honest, half of it is readable.

0


source


I am not suggesting that this is the best way to do it, but it was fun to write:

var fi = new [] { new  { Name= "A"},
                  new  { Name= "B"}, 
                  new  { Name= "C"}};

String.Join(Environment.NewLine, 
        fi.Take(1).Select (f => Tuple.Create(f.Name,"FIRST"))
.Concat(fi.Skip(1).Select (f => Tuple.Create(f.Name,"NONFIRST")))
.Select(t=> String.Format("({0} {1})", t.Item1, t.Item2)))
.Dump();

      

0


source







All Articles