Arrays 如何计算linq中的序列长度

Arrays 如何计算linq中的序列长度,arrays,list,linq,Arrays,List,Linq,我有一个1和0的列表。说:1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,1 我想得到1s序列的最大长度 在这种情况下,序列为3,5,3,1,最大值为5 我有这个代码(使用S.O.问题的答案:) var list=new[]{1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,0,1}.ToList(); var pairs=list.Where((e,i)=>inew{A=e,B=list[i+1]}); var analysisd=pairs.ConvertAll(p

我有一个1和0的列表。说:1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,1

我想得到1s序列的最大长度

在这种情况下,序列为3,5,3,1,最大值为5

我有这个代码(使用S.O.问题的答案:)

var list=new[]{1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();
var pairs=list.Where((e,i)=>inew{A=e,B=list[i+1]});
var analysisd=pairs.ConvertAll(p=>new…不确定如何继续

我也不推荐linq,因为当您可以轻松获得一个解决方案时,它需要更多的时间来获得解决方案

我使用索引0来定位1s的长度

var list = new[]{1,1,1,0,0,1,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();

int previousIndex= -1;
int index = list.IndexOf(0);

int max = index < 0 ? list.Count() : 0;
while(index >=0)
{
    int currentLength = index - previousIndex - 1;
    max = max > currentLength ? max : currentLength;
    previousIndex = index;
    index = list.IndexOf(0, index + 1);

    // if sequence of 1 in the end of array
    if(index < 0)
    {
        currentLength = list.Count() -  previousIndex - 1;
        max = max > currentLength ? max : currentLength;
    }
}

Console.WriteLine(max);
var list=new[]{1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();
int-previousIndex=-1;
int index=list.IndexOf(0);
int max=index<0?list.Count():0;
而(索引>=0)
{
int currentLength=索引-以前的索引-1;
max=max>currentLength?max:currentLength;
previousIndex=指数;
index=list.IndexOf(0,index+1);
//数组末尾1的if序列
如果(指数<0)
{
currentLength=list.Count()-previousIndex-1;
max=max>currentLength?max:currentLength;
}
}
控制台写入线(最大值);

这是一个非常好的可重复使用的解决方案,它使用了answer by的扩展名
GroupAdjanceBy

public静态IEnumerable groupappachenBy(此IEnumerable源,Func谓词)
{
使用(var e=source.GetEnumerator())
{
if(如MoveNext())
{
var list=新列表{e.Current};
var pred=e.电流;
while(如MoveNext())
{
if(谓词(pred,e.Current))
{
列表。添加(如当前);
}
其他的
{
收益回报表;
列表=新列表{e.当前};
}
pred=e.电流;
}
收益回报表;
}
}
}
var list=new[]{1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();
var grouped=list.GroupAdjacentBy((x,y)=>x==y);//将相同的相邻元素分组到子列表中
int result=grouped.Max(s=>s.Count());//获取最长子列表

使用扩展方法为
IEnumerable
提供类似于
String.Split的
拆分

public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> src, Func<T, bool> atSplit) {
    IEnumerable<T> NextSplit(IEnumerator<T> e) {
        while (!atSplit(e.Current)) {
            yield return e.Current;
            if (!e.MoveNext())
                yield break;
        }
    }

    var srce = src.GetEnumerator();
    while (srce.MoveNext())
        yield return NextSplit(srce);
}

这似乎很容易做到:

var list = new[]{1,1,1,0,0,1,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();

var maxOnes =
    list
        .Aggregate(
            new { Max = 0 , Current = 0 },
            (a, x) => x == 0
                ? new { Max = a.Max , Current = 0 }
                : new { Max = a.Max > a.Current + 1
                    ? a.Max
                    : a.Current + 1 , Current = a.Current + 1 })
        .Max;

这是对列表的单次遍历,因此性能非常好。

不知道为什么其他答案会因为LINQ、迭代器和谓词而过于复杂……当基本的
foreach
循环足以找到最大连续序列计数时。没什么奇怪的:

public static int GetMaxSequenceCount( IEnumerable<int> items, int match )
{
    int max = 0;
    int total = 0;

    foreach( int i in items )
    {
        if( i == match )
        {
            total++;
            max = total > max ? total : max;
            continue;
        }

        total = 0;
    }

    return max;
}
public static int GetMaxSequenceCount(IEnumerable项,int匹配)
{
int max=0;
int-total=0;
foreach(项目中的int i)
{
如果(i==匹配)
{
总计++;
最大值=总计>最大值?总计:最大值;
持续
}
总数=0;
}
返回最大值;
}

几个较短的备选方案:

int max1 = string.Concat(list).Split('0').Max().Length;

int max2 = list.Aggregate(new int[2], (a, i) => new[]{Math.Max(a[0], a[1]+i), ++a[1]*i})[0];

int max3 = list.Aggregate(new int[2], (a, i) => { a[1] = ++a[1] * i; a[0] = a.Max(); return a; })[0];

啊,专注于linq我忘了list自己的方法。
IndexOf
你说的“有更多的时间找到解决方案”是什么意思?@Enigmativity我的意思是,在这种情况下,直接进行比较容易,我看不出有任何理由使用linq,这将花费您的时间。@JianpingLiu-您的意思是使用
while
循环更简单、更省时吗?这是一种聪明的方法(天才!)来完成这项工作!但我需要“直接”完成它我正在做的其他事情中重新使用Linq…因此我将对此进行投票,但不能选择它作为解决方案。这
其中
似乎是一种复杂的方式来做
获取(list.Count-1)
。这也是一种聪明的方法。但我正在寻找Linq方法来实际强化……而不是代码中的算法。向上投票您的答案并表示感谢!但这不是选择的答案。抱歉,也许您的问题需要更清楚一些?无论如何,为什么要使用Linq聚合?您愿意解释最后两个吗第一个不适合我。请参阅我对@NetMage在Linq.Split解决方案上的评论。但是,当然,在任何情况下,都是巧妙的.upvoting。@pashute它与公认的答案几乎相同,但它依赖于数字只有0和1,因此不适用于其他数字。它以2
0
变量
new int[2]开始
表示最大值和当前最大值。
a[1]=+a[1]*i
currentMax=currentItem==0?0:currentMax+1
,而
a[0]=a.max()是
max=Math.max(max,currentMax)的缩写
这看起来是最好的答案!谢谢。我正在浏览其他答案,可能会将其标记为答案。@Enigmativity在没有任何辅助方法的情况下做了类似的事情,(Slai写了一篇非常简洁的文章,但不清楚它是如何使用带乘法的零来停止继续聚合的)。仍然非常感谢!!因为我想知道如何在linq中实现这一点。我知道如何使用常规编程实现。可读性强,简单,简短(尽管不如@Slai的简短)
var list = new[]{1,1,1,0,0,1,1,1,1,1,0,1,1,1,0,0,0,1}.ToList();

var maxOnes =
    list
        .Aggregate(
            new { Max = 0 , Current = 0 },
            (a, x) => x == 0
                ? new { Max = a.Max , Current = 0 }
                : new { Max = a.Max > a.Current + 1
                    ? a.Max
                    : a.Current + 1 , Current = a.Current + 1 })
        .Max;
public static int GetMaxSequenceCount( IEnumerable<int> items, int match )
{
    int max = 0;
    int total = 0;

    foreach( int i in items )
    {
        if( i == match )
        {
            total++;
            max = total > max ? total : max;
            continue;
        }

        total = 0;
    }

    return max;
}
int max1 = string.Concat(list).Split('0').Max().Length;

int max2 = list.Aggregate(new int[2], (a, i) => new[]{Math.Max(a[0], a[1]+i), ++a[1]*i})[0];

int max3 = list.Aggregate(new int[2], (a, i) => { a[1] = ++a[1] * i; a[0] = a.Max(); return a; })[0];