使用C#,LINQ如何一次又一次地在标记之间选择项目?

Dav*_*ith 5 c# linq

说我有一个字符串数组:

string[] strArray = {"aa", "bb", "xx", "cc", "xx", "dd", "ee", "ff", "xx","xx","gg","xx"};
Run Code Online (Sandbox Code Playgroud)

如何使用LINQ将"xx"标记之间的字符串作为组提取?

通过将它们写入控制台说:

cc
dd,ee,ff
gg
Run Code Online (Sandbox Code Playgroud)

Meh*_*ari 16

纯功能解决方案(无突变):

string[] strArray = { "aa", "bb", "xx", "cc", "xx", "dd", 
                      "ee", "ff", "xx", "xx", "gg", "xx" };

var result = 
 strArray.Aggregate((IEnumerable<IEnumerable<string>>)new IEnumerable<string>[0],
   (a, s) => s == "xx" ? a.Concat(new[] { new string[0] })
      : a.Any() ? a.Except(new[] { a.Last() })
                   .Concat(new[] { a.Last().Concat(new[] { s }) }) : a)
         .Where(l => l.Any());

// Test
foreach (var i in result)
  Console.WriteLine(String.Join(",", i.ToArray()));
Run Code Online (Sandbox Code Playgroud)

如果要过滤掉最后一个标记后的结果:

string[] strArray = { "aa", "bb", "xx", "cc", "xx", "dd", 
                      "ee", "ff", "xx", "xx", "gg", "xx"};

var result = 
  strArray.Aggregate(
    new { C = (IEnumerable<string>)null, 
          L = (IEnumerable<IEnumerable<string>>)new IEnumerable<string>[0] },
    (a, s) => s == "xx" ? a.C == null
        ? new { C = new string[0].AsEnumerable(), a.L }
        : new { C = new string[0].AsEnumerable(), L = a.L.Concat(new[] { a.C }) } 
        : a.C == null ? a : new { C = a.C.Concat(new[] { s }), a.L }).L
          .Where(l => l.Any());

// Test
foreach (var i in result)
  Console.WriteLine(String.Join(",", i.ToArray()));
Run Code Online (Sandbox Code Playgroud)

  • 为邪恶的lambda功夫+1.出于实际目的,这可能不是最具可读性(尽管它不太糟糕),但它仍然令人印象深刻! (2认同)

Sam*_*uel 5

更好的方法可能是编写通用的IEnumerable<T>拆分扩展方法,然后选择所需的结果部分。

public static class IEnumerableExtensions
{
  public static IEnumerable<IEnumerable<TSource>> Split<TSource>(
                     this IEnumerable<TSource> source, TSource splitter)
  {
    if (source == null)
      throw new ArgumentNullException("source");
    if (splitter == null)
      throw new ArgumentNullException("splitter");

    return source.SplitImpl(splitter);
  }

  private static IEnumerable<IEnumerable<TSource>> SplitImpl<TSource>(
                     this IEnumerable<TSource> source, TSource splitter)
  {
    var list = new List<TSource>();

    foreach (TSource item in source)
    {
      if (!splitter.Equals(item))
      {
        list.Add(item);
      }
      else if (list.Count > 0)
      {
        yield return list.ToList();
        list.Clear();
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud) 像这样使用
static void Main(string[] args)
{
  string[] strArray = { "aa", "bb", "xx", "cc", "xx", "dd",
                        "ee", "ff", "xx", "xx", "gg", "xx" };

  var result = strArray.Split("xx");
  foreach (var group in result.Skip(1).Take(3))
  {
    Console.WriteLine(String.Join(",", group.ToArray()));
 }

  Console.ReadKey(true);
}
Run Code Online (Sandbox Code Playgroud) 然后您得到所需的输出
cc
dd,ee,ff
gg
Run Code Online (Sandbox Code Playgroud)