按元素拆分列表

kos*_*kov 14 c# linq

我有这样的1和0的列表:

var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1}
Run Code Online (Sandbox Code Playgroud)

两个项目之间,只能是一个零.如何将该列表拆分为0的子列表?

换句话说:如果我有这样的字符串:string myString = "111011011110111111011101"那么很容易将它分成0个字符串.但如何用列表来做呢?这个例子shoudl产生这些子列表:

1,1,1
1,1
1,1,1,1
1,1,1,1,1,1
1,1,1
1
Run Code Online (Sandbox Code Playgroud)

那么有没有更好的方法然后将每个元素转换为字符串,加入它们并做我展示可以用字符串做什么?

Mar*_*age 10

您可以通过将输入序列转换为序列序列来解决您的问题,就像LINQ GroupBy一样.但是,在您的情况下,您正在对输入序列的更改进行分组.也许有可能将现有的LINQ运算符组合起来GroupBy,Zip并将其组合Skip成一些你想要的东西,但我认为创建一个迭代器块更容易(并且表现得更好),该迭代器块查看输入序列中的项目对:

static class EnumerableExtensions {

  public static IEnumerable<IEnumerable<T>> GroupOnChange<T>(
    this IEnumerable<T> source,
    Func<T, T, Boolean> changePredicate
  ) {
    if (source == null)
      throw new ArgumentNullException("source");
    if (changePredicate == null)
      throw new ArgumentNullException("changePredicate");

    using (var enumerator = source.GetEnumerator()) {
      if (!enumerator.MoveNext())
        yield break;
      var firstValue = enumerator.Current;
      var currentGroup = new List<T>();
      currentGroup.Add(firstValue);
      while (enumerator.MoveNext()) {
        var secondValue = enumerator.Current;
        var change = changePredicate(firstValue, secondValue);
        if (change) {
          yield return currentGroup;
          currentGroup = new List<T>();
        }
        currentGroup.Add(secondValue);
        firstValue = secondValue;
      }
      yield return currentGroup;
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

GroupOnChange将获取输入序列中的项目并将它们分组为一系列序列.如果是,则启动新组changePredicate.

您可以使用GroupOnChange您根据需要精确地分割输入序列.然后,您必须使用删除作为值为零的组Where.

var groups = items
  .GroupOnChange((first, second) => first != second)
  .Where(group => group.First() != 0);
Run Code Online (Sandbox Code Playgroud)

如果输入是类实例并且您希望按该类的属性进行分组,则也可以使用此方法.然后,您必须相应地修改谓词以比较属性.(我知道你需要这个,因为你问了一个现在删除的问题,这个问题稍微复杂一点,输入序列不仅仅是数字,而是带有数字属性的类.)

  • 哇,你很快......只需3分钟就可以写出来吗? (5认同)
  • @ThomasLevesque:不,kosnkov问了另一个更复杂的问题,但问题相同,但有很多负面评论,所以他删除了它.不知道发生了什么,我通过我的解决方案只是发现我无处发布它.然后我发现了这个问题,几乎可以立即回答. (3认同)
  • 那么你找到这个问题的好事,你回答浪费会是一种耻辱;) (3认同)

Tho*_*que 6

您可以编写这样的扩展方法:

public static class Extensions
{
    public static IEnumerable<IEnumerable<TSource>> Split<TSource>(this IEnumerable<TSource> source, TSource splitOn, IEqualityComparer<TSource> comparer = null)
    {
        if (source == null)
            throw new ArgumentNullException("source");
        return SplitIterator(source, splitOn, comparer);
    }

    private static IEnumerable<IEnumerable<TSource>> SplitIterator<TSource>(this IEnumerable<TSource> source, TSource splitOn, IEqualityComparer<TSource> comparer)
    {
        comparer = comparer ?? EqualityComparer<TSource>.Default;
        var current = new List<TSource>();
        foreach (var item in source)
        {
            if (comparer.Equals(item, splitOn))
            {
                if (current.Count > 0)
                {
                    yield return current;
                    current = new List<TSource>();
                }
            }
            else
            {
                current.Add(item);
            }
        }

        if (current.Count > 0)
            yield return current;
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1};
var result = list.Split(0);
Run Code Online (Sandbox Code Playgroud)


ASh*_*ASh 6

int c = 0;
var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1};

var res = list
    // split in groups and set their numbers
    // c is a captured variable
    .Select(x=>new {Item = x, Subgroup = x==1 ? c : c++})
    // remove zeros
    .Where(x=>x.Item!=0)
    // create groups
    .GroupBy(x=>x.Subgroup)
    // convert to format List<List<int>>
    .Select(gr=>gr.Select(w=>w.Item).ToList())
    .ToList();
Run Code Online (Sandbox Code Playgroud)


Ale*_*nda 6

您可以按下一个零的索引进行分组:

    static void Main(string[] args)
    {
        var list = new List<int> { 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 };
        var result = list.Select((e, i) => new { Element = e, Index = i })
            .Where(e => e.Element == 1)
            .GroupBy(e => list.IndexOf(0, e.Index));
    }   
Run Code Online (Sandbox Code Playgroud)