如何判斷 Collection 的元素是否重複?
實務上遇到的問題,不過 Collection 似乎沒有內建方法可用,需動用一點小技巧。
Version
PHP 7.0.0
Laravel 5.2.30
Collection 包含重複元素
CollectionTest.php 1 1GitHub Commit : 單元測試 : Collection 含有重複 Element1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18use App\Services\CollectionDemo;
class CollectionTest extends TestCase
{
/** @test */
public function Collection含有重複Element()
{
/** arrange */
$fake = collect([1, 1, 2, 3]);
$target = App::make(CollectionDemo::class);
/** act */
$actual = $target->hasDuplicated($fake);
/** assert */
$this->assertTrue($actual);
}
}
第 9 行1
$fake = collect([1, 1, 2, 3]);
特別設計含有重複元素的 collection,1
為重複元素。
CollectionDemo.php 2 2GitHub Commit : 判斷 Collection 是否含有重複 Element1
2
3
4
5
6
7
8
9
10
11
12
13
14
15namespace App\Services;
use Illuminate\Support\Collection;
class CollectionDemo
{
/**
* @param Collection $cols
* @return bool
*/
public function hasDuplicated(Collection $cols) : bool
{
return ($cols->count() != $cols->unique()->count());
}
}
使用 collection 內建的 unique()
,它會傳回一個沒有重複的新 collection。
若兩個 collection 的 count()
不一樣,表示此 collection 必含重複元素。
元素重複於 Collection 內
CollectionTest.php 3 3GitHub Commit : 單元測試 : Element 在 Collection 內重複1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18use App\Services\CollectionDemo;
class CollectionTest extends TestCase
{
/** @test */
public function Element在Collection內重複()
{
/** arrange */
$fake = collect([1, 1, 2, 3]);
$target = App::make(CollectionDemo::class);
/** act */
$actual = $target->isDuplicated($fake, 1);
/** assert */
$this->assertTrue($actual);
}
}
12 行1
2/** act */
$actual = $target->isDuplicated($fake, 1);
第一個參數傳入 collection,第二個參數傳入元素,判斷此元素是否在 collection 內重複。
CollectionDemo.php 4 4GitHub Commit : 判斷 Element 是否重複於 Collection1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20namespace App\Services;
use Illuminate\Support\Collection;
class CollectionDemo
{
/**
* @param Collection $cols
* @param int $element
* @return bool
*/
public function isDuplicated(Collection $cols, int $element) : bool
{
$cnt = $cols->filter(function (int $value) use ($element) {
return ($value === $element);
})->count();
return ($cnt > 1);
}
}
使用 collection 內建的 filter()
,傳入一個 closure,filter 出符合傳入元素值的新 collection。
若新 collection 的 count()
大於 1
,表示重複了。
Conclusion
- Laravel 的 collection 相當好用,若能用的巧,可以幾乎完全不用寫
for
或foreach
,程式相當精簡。
Sample Code
完整的範例可以在我的 GitHub 上找到。