所以,我有一个列表:
["item1"]
["item2"]
["item3"]
我希望列表看起来像这样:
[""]
["item1"]
[""]
["item2"]
[""]
["item3"]
一个简单的从后往前的循环就能实现这个功能:
for (int i = list.Count-1; i >= 0; i--)
list.Insert(i, string.Empty);
但我想知道是否有更优雅的方法使用LINQ来完成这个任务?
Intersperse
的扩展方法。这样,意义清晰且代码可重用。代码取自Enumerable.Intersperse的扩展方法,稍作修改以在第一位置包括一个空字符串。请保留HTML标签。public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element)
{
foreach (T value in source)
{
yield return element;
yield return value;
}
}
var intersperced = list.Intersperce("");
- dav_i以下是具体步骤:
list = list.SelectMany(x => new [] { string.Empty, x }).ToList();
但需要注意的是,这样会创建不必要的数组。如果您的列表足够大,这可能会成为一个问题。相反,我建议使用循环创建一个新的具有容量的列表并填充它:
var newList = new List<string>(list.Count * 2);
int j = 0;
for(int i = 0; i < list.Count * 2; i++)
newList.Add(i % 2 == 0 ? string.Empty : list[j++]);
List<T>
在每次添加/删除元素时都不会被重新调整大小。内部它使用数组作为支持字段,支持字段的大小通过2的幂级数增加(从4开始)。默认情况下,大小永远不会减小。要获取支持字段的大小,可以使用 list.Capacity
。如果调用了 list.TrimExcess()
,则支持字段才会被缩小。因此,直接设置列表的大小可能仍然更快,但实际上这几乎没有任何影响。 - David Raab您可以使用SelectMany LINQ扩展来完成此操作:
void Main()
{
List<String> items = new List<String>()
{
"1",
"2",
"3"
};
var result = items
.SelectMany(item => new String[] {"Some value", item})
.ToList();
PrintItems(result);
}
void PrintItems<T>(IEnumerable<T> items)
{
foreach(var item in items)
{
Console.WriteLine(item);
}
}
使用Aggregate的另一个一行代码:
List<string> result = list.Aggregate(new List<string>(list.Count * 2), (a, x) => { a.Add(""); a.Add(x); return a; });
x => [ "", x ]
。而SelectMany
正好可以做到这一点。为什么创建一个List
并向其中添加元素更清晰呢?实际上,理解Selman22编写的for
循环的真正意图要困难得多。 - David Raab