[TOC]
## Traversable数据查询示例
### 数据源
~~~
use Pinq\ITraversable, Pinq\Traversable;
//将传入的元素构造成可遍历的数据源
$numbers = Traversable::from(range(1, 100));
$strings = Traversable::from(['foo', 'bar', 'baz', 'tear', 'cow', 'tripod', 'whisky', 'sand', 'which']);
~~~
### 过滤
~~~
//遍历数组中与 2 取余数等于 0的元素
foreach($numbers->where(function ($i) { return $i % 2 === 0; }) as $number) {
//2, 4, 6, 8...
}
//遍历数组中与 2 取余数等于 1的元素
foreach($numbers->where(function ($i) { return $i % 2 === 1; }) as $number) {
//1, 3, 5, 7....
}
//筛选出数组中所有的值以字母“w”开头的元素
foreach($strings->where(function ($i) { return strpos($i, 'w') === 0; })) as $string) {
//'whiskey', 'which'
}
$strArr=$strings->where(function ($i, $key) {
return $key % 2 === 0;
});
foreach($strArr as $string) {
//'foo', 'baz', 'cow'
}
~~~
### 排序
~~~
foreach($numbers->orderByAscending(function ($i) { return -$i; }) as $number) {
//100, 99, 98, 97, 96...
}
foreach($strings
->orderByAscending(function ($i) { return $i[0]; })
->thenByDescending(function ($i) { return $i[2]; }) as $string) {
//'baz', 'bar', 'cow', 'foo'...
}
~~~
### 分组
~~~
foreach($numbers->groupBy(function ($i) { return $i % 2; }) as $group) {
//Traversable: [1, 3, 5, 7...], Traversable: [2, 4, 6, 8...]
}
foreach($strings->groupBy(function ($i) { return $i[0]; }) as $string) {
//Traversable: ['foo'], Traversable: ['bar', 'baz'], Traversable: ['tear', 'tripod']...
}
~~~
### 关联
~~~
foreach($numbers
->join(range(10, 20))
->onEquality(function ($outer) { return $outer * 2; }, function ($inner) { return $inner; })
->to(function($outer, $inner) { return $outer . ':' . $inner; }) as $joined) {
//'5:10', '6:12', '7:14', '8:16', '9:18', '10:20'
}
foreach($numbers
->groupJoin($strings)
->onEquality(function ($outer) { return $outer; }, 'strlen')
->to(function($outer, ITraversable $innerGroup) { return $outer . ':' . $innerGroup->implode('|'); }) as $joined) {
//'1:', '2:', '3:foo|bar|baz|cow', '4:tear|sand', '5:which', '6:tripod|whisky', '7:'...
}
foreach($numbers
->groupJoin($numbers)
->on(function ($outer, $inner) { return $outer >= $inner; })
->to(function($outer, ITraversable $innerGroup) { return $outer . ':' . $innerGroup->implode('|'); }) as $joined) {
//'1:1', '2:1|2', '3:1|2|3', '4:1|2|3|4', '5:1|2|3|4|5'...
}
~~~
### 选择
~~~
foreach($numbers->select(function ($i) { return $i * 10; }) as $number) {
//10, 20, 30, 40...
}
foreach($strings->select(function ($i) { return $i . '-poo'; }) as $string) {
//'foo-poo', 'bar-poo', 'baz-poo', 'tear-poo'...
}
foreach($strings->select('strlen') as $length) {
//3, 3, 3, 4...
}
~~~
### 多选
~~~
foreach($strings->selectMany(function ($i) { return str_split($i); }) as $character) {
//'f', 'o', 'o', 'b', 'a'...
}
~~~
### 聚合
~~~
$numbers->aggregate(function ($i, $k) { return $i * $k }); //100! (1 * 2 * 3 * 4...)
$numbers->count(); //100
$numbers->isEmpty(); //false
$numbers->sum(); //5050 (1 + 2 + 3 + 4...)
$numbers->average(); //50.5
$numbers->maximum(); //100
$numbers->implode('-'); //'1-2-3-4-5-6...'
$strings->implode(''); //'foobarbaztear...'
$strings->all(function ($i) { return strlen($i) >= 3; }); //true
$strings->any(function ($i) { return strpos($i, 'z') !== false; }); //false
$strings->average('strlen'); //4.111...
~~~
### 链式调用
~~~
$numberData = $numbers
->where(function ($i) { return $i % 2 === 0; }) //Only even values
->orderByDescending(function ($i) { return $i; }) //Order from largest to smallest
->groupBy(function ($i) { return $i % 7; }) //Put into seven groups
->where(function (ITraversable $i) { return $i->count() % 2 === 0; }) //Only groups with an even amount of values
->select(function (ITraversable $numbers, $isEven) {
return [
'isEven' => $isEven,
'average' => $numbers->average(),
'count' => $numbers->count(),
'numbers' => $numbers->asArray(),
];
});
~~~