寻找一个 linq 解决方案来取代 for 循环



我经常遇到这样的例子。 在这种情况下,我想在以前加载的名为 files 的变量中的每个 FileInfo 对象填充一个字符串生成器,该变量当然包含一堆 FileInfo 对象。 对于第一个对象,我想在文本后添加 FIRST,然后对于其他所有我想添加 NOTFIRST。 要使用 forloop 执行此操作,我必须设置一个计数器,执行 if 语句并增加计数器。

我已经学到了足够多的 linq,它在我的指尖上,但我知道必须有一个优雅的 LINQ 解决方案。

            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));
            }

就个人而言,我会放弃 LINQ 并坚持使用您拥有的内容,只是更简单:

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

(我不清楚为什么您将文件名视为有效的格式字符串......当然,如果它确实是一个有效的格式字符串,你可以将我的两次调用更改为Append()AppendLine()改回带有string.Format()的单次调用(

您可以使用 Select 的重载来提供当前索引:http://msdn.microsoft.com/pl-pl/library/bb534869(v=vs.110(.aspx

我也不喜欢在使用linq时改变状态,所以我会使用String.Join代替。

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

经常在这里问问题,我带着混合的疑问:

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

我不愿意检查字符串生成器的长度,因为我还有其他场景,其中额外的几乎需要使用 linq 函数。

我想我可以很容易地完成以下操作(对于我陈述的示例(:

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

但说实话,它的可读性只有一半。

我并不是说这是最好的方法,但写起来很有趣:

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();

最新更新