我一直遇到这样的例子。在这种情况下,我想在一个名为 files 的先前加载的变量中为每个FileInfo对象填充一个带有新行的stringbuilder,当然它包含一堆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));
}
答案 0 :(得分:7)
就个人而言,我会放弃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()
答案 1 :(得分:2)
您可以使用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"))));
答案 2 :(得分:0)
我经常会在这里提出问题,我选择了各种各样的建议:
foreach (var fi in files)
{
var extra = (fi == files.First() ? "FIRST" : "NOTFIRST");
sb.AppendLine(fi.Name + extra);
}
我不愿意检查stringbuilder的长度,因为我还有其他情况,额外非常需要使用linq函数。
我想我可以轻松完成以下操作(对于我所陈述的例子):
sb.AppendLine(files.First().Name + " FIRST");
sb.AppendLine(String.Join(Environment.NewLine,
files.Skip(1).Select( fi => fi.Name + " NOTFIRST")));
但说实话,它的一半是可读的。
答案 3 :(得分:0)
我并不是说这是最好的方法,但写起来很有趣:
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();