web-dev-qa-db-ja.com

リスト内のすべてのアイテムが偽であるかどうかをブールリストでチェック

List<bool>多数の値。リスト内のすべてのアイテムがfalseと等しいかどうかを確認する最も効率的な方法は何ですか?

31
jacobz

ここでは言及していませんが、非常に高速なソリューションはContainsを使用することです

if (!myList.Contains(true))
    // Great success - all values false! 

ContainsIEnumerable.Anyを比較し、Containsの戻りが速くなりました。私のテストでは、IEnumerable.AllIEnumerable.Anyと同じように実行されましたが、おそらくこれらの両方の機能に内部で同様のアルゴリズムが使用されています。 IEnumerable.ExistsIEnumerable.Anyよりもパフォーマンスが優れていたIEnumerable.Allもチェックしましたが、Containsよりも低速でした。

10,000,000のboolエントリのリスト(同様の結果で0と1のエントリも試しました)で、次のメトリックを思いつきました。

Any=95msで経過

すべて経由の経過= 88ms

Exists by Exists = 27ms

を介して経過(含む)=17ms

〜は〜5.59倍高速ですthan any!

次のコードでテスト済み:

// setup initial vars
var myList = new List<bool>();
for (int x = 0; x < 10000000; x++)
    myList.Add(false);  

var containsAllFalse = false;
Stopwatch sw = new Stopwatch();

// start test
sw.Start();
containsAllFalse = !myList.Any(x => x);
sw.Stop();

// get result for Any
var timeAny = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 2
sw.Restart();
containsAllFalse = myList.All(x => x == false);
sw.Stop();

// get result for All
var timeAll = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 3
sw.Restart();
containsAllFalse = !myList.Exists(x => x == true);
sw.Stop();

// get result for All
var timeExists = sw.ElapsedMilliseconds;

// reset variable state (just in case it affects anything)
containsAllFalse = false;   

// start test 4
sw.Restart();   
containsAllFalse = !myList.Contains(true);          
sw.Stop();

// get result from Contains
var timeContains = sw.ElapsedMilliseconds;

// print results
var percentFaster = Math.Round((double)timeAny / timeContains, 2);
Console.WriteLine("Elapsed via Any = {0}ms", timeAny);
Console.WriteLine("Elapsed via All = {0}ms", timeAll);
Console.WriteLine("Elapsed via Exists = {0}ms", timeExists);
Console.WriteLine("Elapsed via Contains = {0}ms", timeContains);
Console.WriteLine("Contains is ~{0}x faster than Any!", percentFaster);


これは、タイプが2つの状態しか持てないタイプでのみ機能することに注意してください(つまり、Nullable<bool>などの> 2状態の変数は機能しません)

6
ChickenFeet

Enumerable.Any 最初の一致で条件を満たしていることがわかります。 Habibが、AnyをEnumerable.Allとして使用する方が適切であると言ったように、boolの空のリストに対してはtrueを返します。

!lst.Any(c=> c == true);

または Enumerable.All を使用します

lst.All(c=> c == false);
36
Adil

IEnumerable.Any / All の使用に同意します。ただし、現在最も投票されている回答(これを書いている時点では間違っていました)と、Any vs Allの関連するコメントのいくつかに同意しません。

これらの次の操作は、意味的にと同等です。否定はbothの内側、述語、および演算結果に適用されることに注意してください。

_!l.Any(x => f(x))
l.All(x => !f(x))
_

さて、この場合、私たちはこうして探しています:

それがnotの場合、anyの真の値がある場合。

_!l.Any(x => x)  // f(x) = x == true
_

または

every値がnottrueである場合です。

_l.All(x => !x)  // f'(x) = !f(x) = !(x == true)
_

空のリストに特別なものはありません。結果は同じです。 !empty.Any(..)empty.All(..)と同様にfalseであり、上記の同値関係は引き続き有効です。

さらに、bothフォームは遅延評価され、 LINQ To Objects ;で同数の評価が必要です。内部的には、シーケンス実装の違いは、単に述語と結果値のチェックを無効にしているだけです。

17
user2864740

LINQ'sAllメソッドを使用できます。

list.All(x => x == false);

falseに等しい値が見つかった場合、すぐにtrueを返します。

2
Selman Genç