判斷 Collection 元素是否重複的小技巧

實務上遇到的問題,不過 Collection 似乎沒有內建方法可用,需動用一點小技巧。

Version


PHP 7.0.0
Laravel 5.2.30

Collection 包含重複元素


CollectionTest.php 1 1GitHub Commit : 單元測試 : Collection 含有重複 Element

tests/CollectionTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use 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 是否含有重複 Element

Services/CollectionDemo.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace 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 內重複

tests/CollectionTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use App\Services\CollectionDemo;

class CollectionTest extends TestCase
{

/** @test */
public function ElementCollection內重複()
{

/** 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 是否重複於 Collection

Services/CollectionDemo.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace 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 相當好用,若能用的巧,可以幾乎完全不用寫 forforeach,程式相當精簡。

Sample Code


完整的範例可以在我的 GitHub 上找到。

2016-04-26