【问题标题】:LINQ: Adding an item to every second positionLINQ:每隔一个位置添加一个项目
【发布时间】:2014-11-05 18:12:11
【问题描述】:

所以我有一个清单:

["item1"]
["item2"]
["item3"]

我希望列表是这样的:

[""]
["item1"]
[""]
["item2"]
[""]
["item3"]

一个简单的从后到前的循环给了我这个:

for (int i = list.Count-1; i >= 0; i--)
   list.Insert(i, string.Empty);

但我想知道是否有更优雅的方式来使用 LINQ 做到这一点?

【问题讨论】:

  • IMO:Linq 对 quering 有好处 - 对更新/变异不太好 :)
  • 请查看 Selman22 的回答,这有什么不好? :) 但是,是的,你确实有一个通用的观点,它是每个定义的查询机制......但是包含大量的投影能力。
  • 坚持你的做法,Linq 很棒,但下面的示例并没有真正说明意图。用它来查询,但不是所有的东西。
  • @Pompair IMO 他在做什么不是很明显?一个简单的 for 循环更清晰。
  • @Pompair 另外,这不会为您提供添加项目的相同列表,它会为您提供一个新列表 - 如果有的话,那就不好了else 持有对旧列表的引用。

标签: c# linq


【解决方案1】:

您可以使用Intersperse 扩展方法。这样,意思就很清楚了,代码是可重用的。取自 Extension method for Enumerable.Intersperse 的代码稍作修改,在第一个位置也包含一个空字符串。

public static IEnumerable<T> Intersperse<T>(this IEnumerable<T> source, T element)
{
    foreach (T value in source)
    {
        yield return element;
        yield return value;
    }
}

【讨论】:

  • @Pompair 我会说这个解决方案更加优雅 - 当你使用它时,一个内联(并且更容易阅读):var intersperced = list.Intersperce("");
【解决方案2】:

这是一种方法:

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++]);

这将避免每次添加或插入项目时调整列表大小。

【讨论】:

  • A List&lt;T&gt; 不会在每次添加/删除内容时都调整大小。在内部,它使用一个数组作为支持字段,烘焙字段的大小增加了 2 的幂(从 4 开始)。默认情况下,大小永远不会减小。要获得支持字段的大小,您可以询问list.Capacity。仅当您调用 list.TrimExcess() 时,支持字段才会减少。所以直接设置列表的大小仍然可以更快,但它可能根本不重要。
【解决方案3】:

您可以使用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);
    }
}

但如你所知,这不是最有效的方法。

【讨论】:

  • 想知道是否有办法通过在结果数组中添加一次“一些值”来做到这一点。
【解决方案4】:

另一个使用聚合的单行:

List<string> result = list.Aggregate(new List<string>(list.Count * 2), (a, x) => { a.Add(""); a.Add(x); return a; });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2019-10-10
    • 2015-10-11
    • 2017-12-04
    • 1970-01-01
    相关资源
    最近更新 更多