如何将bool列表折叠为整数列表

时间:2015-12-18 20:07:54

标签: c# linq

如果我有一个布尔列表,我如何转换成一个整数列表(或任何其他IEnnumerable<int>)整数,其中每个整数代表使用LINQ的每个布尔字符串的长度?

例如,{true, true, false, false, true, true, true}将成为{2, 3},因为true的第一次运行为2长,第二次运行为3长。或者我必须回去做foreach循环吗?

我对错误值的数量不感兴趣,它们只是重要的,因为它们分隔了真值的运行。

因此{true, true, true, false, true, true, true, true, false, false, true, true, true}将成为{3, 4, 3}

3 个答案:

答案 0 :(得分:7)

这样的事情:

public static class IEnumerableExt
{
    public static IEnumerable<int> ConsecutiveTrues(this IEnumerable<bool> bools)
    {
      var flag=false;
      int count=0;
      foreach(var b in bools)
      {
        if (b)
        {
          count++;
        } else if (flag)
        {
            yield return count;
            count=0;
        }
        flag=b;
      }
      if (flag)
        yield return count;
    }
}

然后用作:

void Main()
{
  var bools=new bool[]{true, true, false, false, true, true, true};
  var results=bools.ConsecutiveTrues();
}

使用纯LINQ方式(主要来自https://stackoverflow.com/a/27574266/856353):

var str = new bool[]{true, true, true, false, true, true, true, true, false, false, true, true, true};

// Retain a horrid mutable sequence which tracks consecutive characters
var sequence = 0;
var grps = str
  .Zip((str.Concat(new bool[]{str.Last()})).Skip(1),
     (prev, current) => new { prev, current })
  .GroupBy(p => new { 
      Ch = p.prev, 
      Sequence = p.current == p.prev
      ? sequence 
      : sequence++})
  .Where(l=>l.Key.Ch==true)
  .Select(l=>l.Count());

答案 1 :(得分:1)

没有糟糕的LINQ,只是糟糕的想法:)。 它可以很好地完成LINQ,但仍然可以知道它的作用。

嗯,我希望如此:)。

List<bool> lst = new List<bool>() { true, true, true, false, true, true,
                                    true, true, false, false, true, true,
                                    true };

var bb =
lst
.Aggregate(new List<int>(), (acc, element) =>
{
    if (element == true && acc.Count < 1) acc.Add(1);
    else if (element == true && acc.Count > 0) acc[acc.Count - 1]++;
    else if(acc.Count > 0 && acc[acc.Count - 1] > 0) acc.Add(0);
    return acc;
}, acc =>
{
    if (acc.Count > 0 && acc[acc.Count - 1] == 0)
    {
        acc.RemoveAt(acc.Count - 1);
    }
    return acc;
});
//{3, 4, 3}

答案 2 :(得分:0)

前段时间我制作了一个寻找连续元素的通用版本。 它适用于任何实现IComparable的东西,并且可以选择,感兴趣的元素是什么。

只是一种思考的食物:)。

public
static
class IEnumerableExtensions
{
    public
    static
    IEnumerable<int> CountConsecutiveElements<TElement>(this IEnumerable<TElement> ie,
                                                             TElement consecutive_element)
        where TElement: IComparable<TElement>
    {
        using(var en = ie.GetEnumerator())
        {
            int i = 0;
            while (en.MoveNext())
            {
                if (en.Current.CompareTo(consecutive_element) == 0) i++;
                else if (i > 0)
                {
                    yield return i;
                    i = 0;
                }
            }
            if (i > 0) yield return i;
        }
    }
}

然后使用很简单:

List<bool> lst = new List<bool>() { true, true, true, false, true, true,
                                    true, true, false, false, true, true,
                                    true };

//var rslt = lst.CountConsecutiveElements(true).ToList();
//there is no need for .ToList()

var rslt = lst.CountConsecutiveElements(true);
//{3, 4, 3}