From e95dc82c23a6cf4d039b00d934122ce2201a831c Mon Sep 17 00:00:00 2001 From: Wendell Adriel Date: Fri, 11 Aug 2023 15:48:51 +0100 Subject: [PATCH] [10.x] Add `percentage` method to Collections (#48034) * Create percentage Collection method * Update percentage to return null for empty collections and add more test cases * formatting --------- Co-authored-by: Taylor Otwell --- .../Collections/Traits/EnumeratesValues.php | 19 +++++++++ tests/Support/SupportCollectionTest.php | 41 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index e95bdcf76ff..f0bd10b1926 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 c4e59e1237a..e52888d7ad3 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. *