这篇笔记用来整顿 Collection 在 Laravel 的理论利用场景。
求和
需要:遍历 $orders 数组,求 price 的和。
<?php
// 引入 package
require __DIR__ . '/vendor/autoload.php';
$orders = [[
'id' => 1,
'user_id' => 1,
'number' => '13908080808',
'status' => 0,
'fee' => 10,
'discount' => 44,
'order_products'=> [['order_id'=>1,'product_id'=>1,'param'=>'6 寸','price'=>555.00,'product'=>['id'=>1,'name'=>'蛋糕名称','images'=>[]]],
['order_id'=>1,'product_id'=>1,'param'=>'7 寸','price'=>333.00,'product'=>['id'=>1,'name'=>'蛋糕名称','images'=>[]]],
],
]];
- 应用传统的 foreach 形式进行遍历:
$sum = 0;
foreach ($orders as $order) {foreach ($order['order_products'] as $item) {$sum += $item['price'];
}
}
echo $sum;
- 应用汇合的 map、flatten、sum:
$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:
$sum = collect($orders)->flatMap(function($order){return $order['order_products'];
})->pluck('price')->sum();
echo $sum;
flatMap:和 map
相似,不过区别在于 flatMap
能够间接应用返回的新汇合。
- 应用汇合的 flatMap、sum:
$sum = collect($orders)->flatMap(function($order){return $order['order_products'];
})->sum('price');
sum:能够接管一个列名作为参数进行求和。
格式化数据
需要:将如下构造的数组,格式化成上面的新数组。
// 带格式化数组
$gates = [
'BaiYun_A_A17',
'BeiJing_J7',
'ShuangLiu_K203',
'HongQiao_A157',
'A2',
'BaiYun_B_B230'
];
// 新数组
$boards = [
'A17',
'J7',
'K203',
'A157',
'A2',
'B230'
];
- 应用 foreach 进行遍历:
$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:
$res = collect($gates)->map(function($gate) {$parts = explode('_', $gate);
return end($parts);
});
- 应用汇合的 map、explode、last、toArray:
$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 分,计算以后用户的工夫得分总和。
$opts = [
'http' => [
'method' => 'GET',
'header' => ['User-Agent: PHP']
]
];
$context = stream_context_create($opts);
$events = json_decode(file_get_contents('http://api.github.com/users/0xAiKang/events', false, $context), true);
- 传统 foreach 形式:
$eventTypes = []; // 事件类型
$score = 0; // 总得分
foreach ($events as $event) {$eventTypes[] = $event['type'];
}
foreach($eventTypes as $eventType) {switch ($eventType) {
case 'PushEvent':
$score += 5;
break;
case 'CreateEvent':
$score += 4;
break;
case 'IssueEvent':
$score += 3;
break;
case 'IssueCommentEvent':
$score += 2;
break;
default:
$score += 1;
break;
}
}
- 应用汇合的 map、pluck、sum 办法:
$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 办法:
$score = $events->pluck('type')->map(function($eventType) {
return collect([
'PushEvent'=> 5,
'CreateEvent'=> 4,
'IssueEvent'=> 3,
'IssueCommentEvent'=> 2
])->get($eventType, 1); // 如果不存在则默认等于 1
})->sum();
- 尝试将该需要,封装成一个类:
class 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));
格式化数据
需要:将以下数据格式化成新的构造。
$messages = [
'Should be working now for all Providers.',
'If you see one where spaces are in the title let me know.',
'But there should not have blank in the key of config or .env file.'
];
// 格式化之后的后果
- Should be working now for all Providers. \n
- If you see one where spaces are in the title let me know. \n
- But there should not have blank in the key of config or .env file.
- 传统的 foreach 形式:
$comment = '-' . array_shift($messages);
foreach ($messages as $message) {$comment .= "\n - ${message}";
}
var_dump($comment);
- 应用汇合的 map、implode 办法:
$comment = collect($messages)->map(function($message){return '-' . $message;})->implode("\n");
var_dump($comment);
多个数组求差
需要:两组数据别离代表去年的营收和往年的营收,求每个月的盈亏状况。
$lastYear = [
6345.75,
9839.45,
7134.60,
9479.50,
9928.0,
8652.00,
7658.40,
10245.40,
7889.40,
3892.40,
3638.40,
2339.40
];
$thisYear = [
6145.75,
6895.00,
3434.00,
9349350,
9478.60,
7652.80,
4758.40,
10945.40,
3689.40,
8992.40,
7588.40,
2239.40
];
- 传统的 foreach 形式:
$profit = [];
foreach($thisYear as $key => $monthly){$profit[$key] = $monthly - $lastYear[$key];
}
var_dump($profit);
- 应用汇合的 zip、first、last:
$profit = collect($thisYear)->zip($lastYear)->map(function($monthly){return $monthly->first() - $monthly->last();});
zip:将给定数组的值与相应索引处的原汇合的值合并在一起。
创立 lookup 数组
需要:将如下数组格式化成上面的后果:
$employees = [
[
'name' => 'example',
'email' => 'example@exmaple.com',
'company' => 'example Inc.'
],
[
'name' => 'Lucy',
'email' => 'lucy@example.com',
'company' => 'ibm Inc.'
],
[
'name' => 'Taylor',
'email' => 'toylor@laravel.com',
'company'=>'Laravel Inc.'
]
];
// 格式化之后的后果
$lookup = [
'example' => 'example@example.com',
'Lucy' =>‘lucy@example.com’,
'Taylor'=> 'toylor@laravel.com'
];
- 传统的 foreach 形式:
$emails = [];
foreach ($employees as $key => $value) {$emails[$value['name']] = $value['email'];
}
- 应用汇合的 reduce 办法:
$emails = collect($employees)->reduce(function($emailLookup, $employee){$emailLookup[$employee['name']] = $employee['email'];
return $emailLookup;
},[]);
reduce:将每次迭代的后果传递给下一次迭代直到汇合缩小为单个值。
- 应用汇合的 pluck 办法:
$emails = collect($employees)->pluck('name', 'email');
参考链接
- collection 在理论开发中的应用