diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index e95bdcf76ff9..f0bd10b19261 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -481,6 +481,25 @@ public function partition($key, $operator = null, $value = null) return new static([new static($passed), new static($failed)]); } + /** + * Calculate the percentage of items that pass a given truth test. + * + * @param (callable(TValue, TKey): bool) $callback + * @param int $precision + * @return float|null + */ + public function percentage(callable $callback, int $precision = 2) + { + if ($this->isEmpty()) { + return null; + } + + return round( + $this->filter($callback)->count() / $this->count() * 100, + $precision + ); + } + /** * Get the sum of the given values. * diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index c4e59e1237ad..e52888d7ad30 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -5634,6 +5634,47 @@ public function testEnsureForInheritance($collection) $data->ensure(\Throwable::class); } + /** + * @dataProvider collectionClassProvider + */ + public function testPercentageWithFlatCollection($collection) + { + $collection = new $collection([1, 1, 2, 2, 2, 3]); + + $this->assertSame(33.33, $collection->percentage(fn ($value) => $value === 1)); + $this->assertSame(50.00, $collection->percentage(fn ($value) => $value === 2)); + $this->assertSame(16.67, $collection->percentage(fn ($value) => $value === 3)); + $this->assertSame(0.0, $collection->percentage(fn ($value) => $value === 5)); + } + + /** + * @dataProvider collectionClassProvider + */ + public function testPercentageWithNestedCollection($collection) + { + $collection = new $collection([ + ['name' => 'Taylor', 'foo' => 'foo'], + ['name' => 'Nuno', 'foo' => 'bar'], + ['name' => 'Dries', 'foo' => 'bar'], + ['name' => 'Jess', 'foo' => 'baz'], + ]); + + $this->assertSame(25.00, $collection->percentage(fn ($value) => $value['foo'] === 'foo')); + $this->assertSame(50.00, $collection->percentage(fn ($value) => $value['foo'] === 'bar')); + $this->assertSame(25.00, $collection->percentage(fn ($value) => $value['foo'] === 'baz')); + $this->assertSame(0.0, $collection->percentage(fn ($value) => $value['foo'] === 'test')); + } + + /** + * @dataProvider collectionClassProvider + */ + public function testPercentageReturnsNullForEmptyCollections($collection) + { + $collection = new $collection([]); + + $this->assertNull($collection->percentage(fn ($value) => $value === 1)); + } + /** * Provides each collection class, respectively. *