2013-04-10 8 views

答えて

16

あなたはEnumerable.Zip経由でこれを行うことができます:

bool sequential = values.Zip(values.Skip(1), (a,b) => (a+1) == b).All(x => x); 

をこれは、値の各ペアを取って、第二は、まず、および返すブール値よりも1以上であるかどうかをチェックすることによって動作します。すべてのペアが基準に適合する場合、値は順次です。


が、これは整数の リストであることを考えると、あなたが使用して、より効率的に、わずかにこれを行うことができます。

bool sequential = values.Skip(1).Select((v,i) => v == (values[i]+1)).All(v => v); 

これをインデックスのみがアクセスすることができる配列に動作します。 Skipコールが効果的にインデックスをシフトするので、values[i]values[i-1]ではなく)を使用することに注意してください。

+0

@dtb固定していただきありがとうございます... –

+0

+1。私はそれが複数のシーケンスを繰り返し反復することを避けるためにAggregate(ちょっと差をつけてください)でもやってもいいと思っています...後で答えとして書くつもりです... –

+0

@AlexeiLevenkov私の2番目のオプションは一度しか反復しませんが、シーケンスはリストです。私は 'Aggregate'でそれをする方法を見ることができますが、あなたのラムダに厄介な副作用がある場合にのみ... :( –

10
bool isSequential = Enumerable.Range(values.Min(), values.Count()) 
           .SequenceEqual(values); 
+0

なぜこれが答えに選ばれなかったのか分かりません。その素晴らしく簡単です。 – user1830285

2

もう1つのオプションは、Aggregateを使用してシーケンスを1回だけ繰り返すことです。

注条件が失敗したときにリードCopsey Aggregateによって提案Allとは異なり、途中で止めることはできないということ...

var s = new int[] {3,4,5,6}.ToList(); 

var isSequential = s.Aggregate 
    (
     new {PrevValue = 0, isFirst = true, Success = true} , 
     (acc, current) => 
      new { 
        PrevValue = current, 
        isFirst = false, 
        Success = acc.Success && (acc.isFirst || (acc.PrevValue == current - 1)) 
       } 
) 
    .Success; 

ファンシーなバージョンが一緒に前の値またはだろう特別なコードを運ぶイテレータを持っているだろう「最初と残り」の反復子を分割することで、任意の列挙型に対して1回の繰り返しでReedのソリューションを実装することができます。

+0

質問がリストに関するものだったので、ToList()を追加しました。私は楽しみの継続を望みます。 –

+1

+1これはうまくいきますが、大きなリストのメモリを大量に消費し、成功したときに短絡することはありません...私はまだ私のオプションのほうが好きです(私の2番目は特に効率的ですそれがリストだと知っている)。 –

-1

あなたはすでにあなたがあなたのリストを持っている数字は、ユニークであることを知っている、ともを並べ替えた場合、シーケンシャルのための最も簡単なチェックだけで

lst[lst.Count - 1] - lst[0] == lst.Count - 1 

では、リスト内の少なくとも1つの要素を想定します。

関連する問題