2016-12-03 55 views
2

我想分割列表就像string.split(split_between_that_value)那样,我该怎么做?分割列表就像string.split()

所以用字符串"some string with spaces" string.Split('')会将它拆分为[some, string, with, spaces]数组。

但是随着含作为项目我不知道如何做到这一点的所有字符列表...

列表:

{'s','o','m','e',' ','s','t','r','i','n','g',' ','w','i','t','h',' ','s','p','a','c','e','s'}

我希望它分裂成列表的列表:

{{'s','o','m','e'},{'s','t','r','i','n','g'},{'w','i','t','h'},{'s','p','a','c','e','s'}}

+0

是List列表? –

+0

@ robert-m没有我的列表是列表 BladeMight

回答

2

有趣的是,还没有一种现有的扩展方法可以实现这一点的盒子。

public static class EnumerableExtensions 
{ 
    public static IEnumerable<IList<TSource>> Split<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
    { 
     var list = new List<TSource>(); 

     foreach (var element in source) 
     { 
      if (predicate(element)) 
      { 
       if (list.Count > 0) 
       { 
        yield return list; 
        list = new List<TSource>(); 
       } 
      } 
      else 
      { 
       list.Add(element); 
      } 
     } 

     if (list.Count > 0) 
     { 
      yield return list; 
     } 
    } 
} 

你会这样称呼它:

var list = new List<char>(){'s','o','m','e',' ','s','t','r','i','n','g',' ','w','i','t','h',' ','s','p','a','c','e','s'}; 
list.Split(x => x == ' ') 
+0

我很确定这个可以使用本地LINQ完成。 – BladeMight

+0

看看这个问题将列表拆分成列表。看起来你可以使用纯LINQ来完成它,但它可能没有那么高效。 http://stackoverflow.com/questions/13845650/use-linq-to-convert-a-list-to-a-list-of-lists –

+0

@BladeMight最后一个'if(list.Count> 0)'使它与''a“中的'string.Split'行为相比有点不一致.Split'返回与'”a“.Split'相同的结果。我会删除它以返回所有结果,或者将其添加到'yield'以排除空条目。 – Slai

2

我会写,如果你想要一个通用的解决方案(东西的不仅仅是IEnumerable<char>作品),你可以像这样的东西自己实现像

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> seq, 
                 Func<T, bool> condition) 
{ 
    List<T> list = new List<T>(); 
    using (var en = seq.GetEnumerator()) 
    { 
     if (en.MoveNext()) 
     { 
      list.Add(en.Current); 

      while (en.MoveNext()) 
      { 
       if (condition(en.Current)) 
       { 
        list.Add(en.Current); 
       } 
       else 
       { 
        yield return list; 
        list = new List<T>(); 
       } 
      } 

      if (list.Any()) 
       yield return list; 
     } 
    } 
} 

的扩展方法和用它作为

var input = new[]{ 's', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', 'w', 'i', 't', 'h', ' ', 's', 'p', 'a', 'c', 'e', 's' }; 
var result = input.GroupWhile(x => x != ' ') 
      .ToList(); 
-1

我的猜测是,你可能会寻找这样的事情:

List<char> list = "some string with spaces".ToList(); 

List<List<char>> lists = list.Aggregate(new List<List<char>>() { new List<char>() }, 
    (a, e) => { if (e == ' ') a.Add(new List<char>()); else a.Last().Add(e); return a; }); 

我希望这是只是一点点比延迟执行速度更快yield答案,但一些List<T>.Add额外的内存分配的可避免与 List<T>.GetRangeList<T>.CopyTo

static List<List<T>> spliT<T>(this List<T> list, T separator = default(T), int start = 0) 
{ 
    var lists = new List<List<T>>(); 

    for (int i = start; i < list.Count; i++) 
     if (list[i].Equals(separator)) 
     { 
      lists.Add(list.GetRange(start, i - start)); 
      start = i + 1; 
     } 

    lists.Add(list.GetRange(start, list.Count - start)); 
    return lists; 
} 
+0

你为什么会'期望这比延迟执行'yield' answers'快一点?你能否详细说明,因为我没有任何理由认为是这样。这两种解决方案都有同样的问题。他们急切地加载源数据。你不知道源数据是什么,你不知道它是否适合内存。如果您的扩展方法的使用者只是打算“拿”第一个'n'元素,会怎样?你的方法仍然会生成整个列表。 –

+0

由于“我希望它分裂成列表清单:”,这将更接近于string.Split行为。我的猜测是,'.ToList'将用于你的扩展中以获得所需的结果,所以我最初的原因是“在延迟执行时使用'.ToList'快于yield'答案”,但在发布之前缩短了它。 – Slai

+0

我没有投票的方式。 –