这篇笔记用来整理Collection 在Laravel 的实际应用场景。
求和
需求:遍历$orders 数组,求price 的和。
1 |
|
使用传统的foreach 方式进行遍历:
1
2
3
4
5
6
7$sum = 0;
foreach ($orders as $order) {
foreach ($order['order_products'] as $item) {
$sum += $item['price'];
}
}
echo $sum;使用集合的map、flatten、sum:
1
2
3
4
5
6
7$sum = collect($orders)->map(function($order){
return $order['order_products'];
})->flatten(1)->map(function($order){
return $order['price'];
})->sum();
echo $sum;
map:遍历集合,返回一个新的集合。
flatten:将多维数组转换为一维。
sum:返回数组的和。
- 使用集合的flatMap、pluck、sum:
1
2
3
4$sum = collect($orders)->flatMap(function($order){
return $order['order_products'];
})->pluck('price')->sum();
echo $sum;
flatMap:和map
类似,不过区别在于flatMap
可以直接使用返回的新集合。
- 使用集合的flatMap、sum:
1
2
3$sum = collect($orders)->flatMap(function($order){
return $order['order_products'];
})->sum('price');
sum:可以接收一个列名作为参数进行求和。
格式化数据
需求:将如下结构的数组,格式化成下面的新数组。
1 | // 带格式化数组 |
使用foreach 进行遍历:
1
2
3
4
5
6
7
8
9
10$res = [];
foreach($gates as $key => $gate) {
if(strpos($gate, '_') === false) {
$res[$key] = $gate;
}else{
$offset = strrpos($gate, '_') + 1;
$res[$key] = mb_substr($gate , $offset);
}
}
var_dump($res);使用集合的map以及php 的explode、end:
1
2
3
4$res = collect($gates)->map(function($gate) {
$parts = explode('_', $gate);
return end($parts);
});使用集合的map、explode、last、toArray:
1
2
3$res = collect($gates)->map(function($gate) {
return collect(explode('_', $gate))->last();
})->toArray();
explode:将字符串进行分割成数组
last:获取最后一个元素
统计GitHub Event
首先,通过此链接获取到个人事件json。
一个 PushEvent计
5 分,一个 CreateEvent
计 4 分,一个 IssueCommentEvent计
3 分,一个 IssueCommentEvent
计 2 分,除此之外的其它类型的事件计 1 分,计算当前用户的时间得分总和。
1 | $opts = [ |
- 传统foreach 方式:
1 | $eventTypes = []; // 事件类型 |
使用集合的map、pluck、sum 方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14$score = $events->pluck('type')->map(function($eventType) {
switch ($eventType) {
case 'PushEvent':
return 5;
case 'CreateEvent':
return 4;
case 'IssueEvent':
return 3;
case 'IssueCommentEvent':
return 2;
default:
return 1;
}
})->sum();使用集合的链式编程,可以很好地解决上面那种多次遍历的问题。
使用集合中的map、pluck、get 方法:
1
2
3
4
5
6
7
8$score = $events->pluck('type')->map(function($eventType) {
return collect([
'PushEvent'=> 5,
'CreateEvent'=> 4,
'IssueEvent'=> 3,
'IssueCommentEvent'=> 2
])->get($eventType, 1); // 如果不存在则默认等于1
})->sum();尝试将该需求,封装成一个类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28class GithubScore {
private $events;
private function __construct($events){
$this->events = $events;
}
public static function score($events) {
return (new static($events))->scoreEvents();
}
private function scoreEvents() {
return $this->events->pluck('type')->map(function($eventType){
return $this->lookupEventScore($eventType, 1);
})->sum();
}
public function lookupEventScore($eventType, $default_value) {
return collect([
'PushEvent'=> 5,
'CreateEvent'=> 4,
'IssueEvent'=> 3,
'IssueCommentEvent'=> 2
])->get($eventType, $default_value); // 如果不存在则默认等于1
}
}
var_dump(GithubScore::score($events));
格式化数据
需求:将以下数据格式化成新的结构。
1 | $messages = [ |
传统的foreach 方式:
1
2
3
4
5$comment = '- ' . array_shift($messages);
foreach ($messages as $message) {
$comment .= "\n - ${message}";
}
var_dump($comment);使用集合的map、implode方法:
1
2
3
4$comment = collect($messages)->map(function($message){
return '- ' . $message;
})->implode("\n");
var_dump($comment);
多个数组求差
需求:两组数据分别代表去年的营收和今年的营收,求每个月的盈亏情况。
1 | $lastYear = [ |
传统的foreach 方式:
1
2
3
4
5$profit = [];
foreach($thisYear as $key => $monthly){
$profit[$key] = $monthly - $lastYear[$key];
}
var_dump($profit);使用集合的zip、first、last:
1
2
3$profit = collect($thisYear)->zip($lastYear)->map(function($monthly){
return $monthly->first() - $monthly->last();
});zip:将给定数组的值与相应索引处的原集合的值合并在一起。
创建lookup 数组
需求:将如下数组格式化成下面的结果:
1 | $employees = [ |
传统的foreach 方式:
1
2
3
4$emails = [];
foreach ($employees as $key => $value) {
$emails[$value['name']] = $value['email'];
}使用集合的reduce 方法:
1
2
3
4$emails = collect($employees)->reduce(function($emailLookup, $employee){
$emailLookup[$employee['name']] = $employee['email'];
return $emailLookup;
},[]);
reduce:将每次迭代的结果传递给下一次迭代直到集合减少为单个值。
- 使用集合的pluck 方法:
1
$emails = collect($employees)->pluck('name', 'email');
返回一维数组
需求:将下面的二维数组,转换为一维数组。
1 | $nums = [ |
- 传统foreach 方式:
1 | $result = []; |
- 使用集合的flatten、map:
1
2
3$result = collect($nums)->flatten(1)->map(function ($num){
return $num;
});
求和
1 | $orders = [ |
- 传统foreach方式:
1 | $total_price = 0; |
array 函数:
1
$total_price = array_sum(array_column($orders, "price"));
使用集合:
1
2
3
4
5
6
7// 方式一:
$total_price = collect($orders)->map(function ($order){
return $order['price'];
})->sum();
// 方式二:
$total_price = collect($orders)->pluck("price")->sum();
分组
1 | $products = [ |
使用集合:
1 | $product = collect($products)->pluck("brand"); |