皮带 / 下划线
将方形物品推入圆形孔中
Requires
- php: >=5.4.0
- symfony/property-access: ~2.0
Requires (Dev)
- phpunit/phpunit: 4.*
This package is not auto-updated.
Last update: 2024-09-24 03:08:06 UTC
README
将圆形物品推入方形孔中。
Belt.Underscore
是一个工具库,使在PHP中使用数组变得更加愉快。
安装
通过Composer
$ composer require belt/underscore
使用方法
以下示例假设您已包含Underscore实用程序
use Belt\_;
一些示例可能看起来有些牵强,但实际上非常实用。例如,假设我们有一个虚构的社会网络,并且(出于某种原因)我们想要获取所有已认证用户的18岁以上的2度朋友(朋友的朋友)的姓名。突然,这变得非常简单!
_::create($user->getFriends())->map(function ($f) { return $f->getFriends(); })->select(function ($f) { return $f->getAge() > 18; })->pluck('username');
现在(出于更奇怪的原因),我们想知道所有18岁以上的2度朋友的第三度朋友(朋友的朋友的朋友)的总数。
_::create($user->getFriends())->map(function ($f) { return $f->getFriends(); })->select(function ($f) { return $f->getAge() > 18; })->reduce(function ($s, $f) { return $s + count($f->getFriends()); });
就这些!
注意:在示例中,当返回值注释指示数组时,实际的返回值是一个新的
_
实例!您可以通过调用toArray
方法来获取实际的PHP数组值。
_
类也实现了ArrayAccess
,因此您可以像使用普通数组一样访问它
$groups = _::create($user->getFriends())->groupBy(function ($friend) { $name = $friend->getName(); return $name[0]; }); $groups['A'] = ...; // All friends with the letter 'A' as the first letter in their name
此外,您还可以通过foreach
循环遍历容器
$users = _::create(['alice', 1337, 'bob', 42])->chunk(2); foreach ($users as $name => $karma) { // ... }
all
对容器中的每个元素调用给定的callback
。如果回调返回false
,则方法立即返回false
并停止枚举。如果所有回调调用都返回true
,则all
返回true
。
_::create([1, 2, 3])->all(function ($n) { return $n > 0; }); // true
any
对容器中的每个元素调用给定的callback
。如果回调返回true
,则方法立即返回true
并停止枚举。如果所有回调调用都返回false
,则any
返回false
。
_::create([1, 2, 3])->any(function ($n) { return $n > 2; }); // true
chunk
将容器分成一个新数组,大小为n
。
_::create([1, 2, 3, 4])->chunk(2); // [[1, 2], [3, 4]]
combine
将容器与另一个数组合并为键/值对。
_::create([1, 2, 3])->combine(['foo', 'bar', 'baz']); // [1 => 'foo', 2 => 'bar', 3 => 'baz']
concat
返回一个新数组,该数组是将给定的array
连接到容器末尾的结果。
_::create([1, 2])->concat([3, 4]); // [1, 2, 3, 4]
dict
将键/值对的数组转换为逻辑字典。
_::create([[1, 2], [3, 4]])->dict(); // [1 => 2, 3 => 4]
如果您有一个扁平的数组,可以在调用dict
之前调用chunk(2)
。
_::create([1, 2, 3, 4])->chunk(2)->dict(); // [1 => 2, 3 => 4]
each
对容器中的每个元素调用给定的回调一次,将元素作为参数传递。
_::create([1, 2, 3, 4])->each(function ($n) { printf("%d\n", $n); }); // outputs: 1\n2\n3\n4\n
each
还支持两个和三个参数版本
_::create([1, 2, 3, 4])->each(function ($n, $i) { printf("%d: %d\n", $i, $n); }); //outputs: 0: 1\n1: 2\n2: 3\n3: 4\n _::create([1, 2, 3, 4]->each(function ($n, $i, $array) { // ... }));
find
将容器中的每个条目传递给给定的回调,返回回调不是false
的第一个元素。如果没有条目匹配,则返回null
。
_::create([1, 2, 3, 4])->find(function ($n) { return $n > 2; }); // 3
first
返回容器中的前n
个元素。
_::create([1, 2, 3, 4])->first(2); // [1, 2]
flatten
返回一个新的一维数组,它是容器递归展平的结果。
_::create([1, [2], [3, [4]]])->flatten(); [1, 2, 3, 4]
提示:如果您只想展平数组的某一层,则可能需要使用
flatMap
!
flatMap
返回一个新的数组,其中包含对容器中的每个元素调用回调一次的连接结果。
_::create([1, 2, 3, 4])->flatMap(function ($n) { return [$n, $n]; }); // [1, 1, 2, 2, 3, 3, 4, 4] _::create([1, 2, 3, 4])->flatMap(function ($n) { return [$n, [$n]]; }); // [1, [1], 2, [2], 3, [3], 4, [4]]
这看起来可能有点荒谬,但这是一个实际非常有用的函数,当与其它函数结合使用时!例如,您可以创建一个(虚构的)用户的字典。
_::create([new User('bob', 32), new User('alice', 35)])->flatMap(function ($u) { return [$n->getName(), $n->getAge()]; })->chunk(2)->dict(); // ['bob' => 32, 'alice' => 35]
这最终允许我们,作为开发者,在映射数组时创建键/值对!太好了!
groupBy
根据给定的回调结果对容器进行分组。
_::create([1, 2, 3, 4])->groupBy(function ($n) { return $n % 2; }); // [0 => [2, 4], 1 => [1, 3]] _::create(['foo', 'bar', 'baz'])->groupBy(function ($s) { return $s[0]; }); // ['f' => ['foo'], 'b' => ['bar', 'baz']]
有
_::create([1, 2, 3, 4])->has(2); // true _::create([1, 2, 3, 4])->has(0); // false
indexOf
返回给定对象在容器中的索引,如果元素未找到,则返回null
。
_::create([1, 2, 3, 4])->indexOf(2); // 1 _::create([1, 2, 3, 4])->indexOf(0); // null
inject
通过应用二进制运算,结合容器的所有元素。
_::create([1, 2, 3])->inject([], function ($m, $n) { $m[$n] = $n * $n; return $m; }); // [1 => 1, 2 => 4, 3 => 9] _::create(['foo', 'bar', 'baz'])->inject('', function ($m, $s) { $m .= $s; }); // foobarbaz
注意:这是之前提到的注意事项的唯一例外。这里的返回值是最后一次迭代的返回值。
join
返回一个字符串,其中包含所有容器的元素,这些元素通过提供的分隔符字符串连接。
_::create([1, 2, 3, 4])->join(''); // 1234 _::create([1, 2, 3, 4])->join(','); // 1,2,3,4
last
返回容器中的最后n
个元素。
_::create([1, 2, 3, 4, 5, 6])->last(2); // [5, 6]
map
对容器中的每个元素调用给定的回调函数。创建一个新数组,包含由块返回的值。
如果给定的回调返回null
,则跳过返回数组中的该元素。
_::create([1, 2, 3, 4])->map(function ($n) { return $n * $n; }); // [1, 4, 9, 16] _::create([1, 2, 3, 4])->map(function ($n) { return $n % 2 ? $n * $n : null; }); // [1, 9]
max
返回给定回调返回最大整数的元素。
_::create('1', 'two', 'three')->max(function ($s) { return strlen($s); }); // 'three'
min
返回给定回调返回最小整数的元素。
_::create('1', 'two', 'three')->min(function ($s) { return strlen($s); }); // '1'
none
测试给定的回调是否为容器中的每个元素返回false
。
_::create([1, 2, 3, 4])->none(function ($n) { return $n < 0; }); // true _::create([1, 2, 3, 4])->none(function ($n) { return $n > 0; }); // false
partition
根据给定块的布尔返回值,将容器分割成两个数组。
_::create(['A', 'B', 'C', 'AA'])->partition(function ($s) { return $s[0] == 'A'; }); // [['A', 'AA'], ['B', 'C']]
pluck
返回一个新数组,它是通过在容器中的每个元素上检索给定属性路径的结果。
_::create([new User('bob'), new User('alice')])->pluck('username'); // ['bob', 'alice']
product
通过假设所有值都可以转换为double值来计算容器的乘积。
_::create([1, 2, 3])->product(); // 6
reduce
将容器减少到单个值。
reduce的常见示例是对数组中的所有值求和。
_::create([1, 2, 3, 4])->reduce(function ($memo, $n) { return $memo + $n; }); // 10
Reduce还允许您在减少数组之前设置一个初始值。
_::create([1, 2, 3, 4])->reduce(function ($s, $n) { return $s + $n; }, 10); // 20
reject
返回一个新数组,其中包含所有给定的回调返回false
的元素。
_::create([1, 2, 3, 4])->reject(function ($n) { return ($n % 2) == 0; }); // [1, 3]
reverse
返回一个新的数组,它是容器反转的。
_::create([1, 2, 3, 4])->reverse(); // [4, 3, 2, 1]
rotate
返回一个新数组,该数组绕提供的索引旋转。
_::create([1, 2, 3, 4, 5, 6])->rotate(2); // [3, 4, 5, 6, 1, 2] _::create([1, 2, 3, 4, 5, 6])->rotate(-2); // [5, 6, 1, 2, 3, 4]
sample
从容器中返回一个随机元素。
_::create([1, 2, 3, 4, 5, 6])->sample(); // Basically a dice roll...
select
返回一个新数组,其中包含所有给定的块返回true
的元素。
_::create([1, 2, 3, 4])->select(function ($n) { return ($n % 2) == 0; }); // [2, 4]
shuffle
返回一个新数组,它是打乱的。
_::create([1, 2])->shuffle(); // Either [1, 2] or [2, 1]
skip
跳过前n
个元素,并返回剩余的数组。
_::create([1, 2, 3, 4, 5, 6])->skip(2); // [3, 4, 5, 6]
slice
返回一个子数组,它从给定的起始索引包含给定数量的元素。
_::create([1, 2, 3, 4])->slice(1, 2); // [2, 3]
snip
剪掉数组的末尾。返回不包含最后n
个元素的容器。
_::create([1, 2, 3, 4, 5, 6])->snip(2); // [1, 2, 3, 4]
sort
返回排序后的容器。
_::create([1, 4, 2, 3])->sort(); // [1, 2, 3, 4]
sortBy
使用给定回调的返回值作为排序标准对所有对象进行排序。
$rhombas = new Shape('rhombas'); $ellipse = new Shape('ellipse'); $hexagon = new Shape('hexagon'); _::create([ $rhombas, $ellipse, $hexagon ])->sortBy(function ($s) { return $s->getName(); }); // [ $ellipse, $hexagon, $rhombas ]
sum
通过将值转换为double来对所有对象求和。
_::create([1, 2, 3, 4])->sum(); // 10
transpose
假设容器是数组的数组,并转置行和列。
_::create([[1, 2, 3], [4, 5, 6]])->transpose(); // [[1, 4], [2, 5], [3, 6]]
uniq
通过从容器中删除重复值来返回一个新数组。
_::create([1, 2, 3, 1, 2, 4, 1, 2, 5])->uniq(); // [3, 4, 5]
without
返回一个新数组,其中从容器中移除了给定数组中的对象。
_::create([1, 2, 4, 3])->without([4]); // [1, 2, 3] _::create([1, 2, 3, 4, 5])->without([4, 5]); // [1, 2, 3]
pop
将容器视为堆栈,并移除最后一个对象,返回它。
_::create()->push(1)->push(2)->push(3)->pop(); // 3
push
将容器视为堆栈,并将给定的对象添加到容器的末尾。
_::create()->push(1)->push(2)->push(3); // [1, 2, 3]
shift
移除容器中的第一个对象并返回它。
_::create([1, 2, 3])->shift(); // 1
unshift
将给定的对象插入到容器的开头,并将容器中的所有其他对象向上移动一个索引。
_::create([2, 3])->unshift(1); // [1, 2, 3]
split
返回一个新数组,该数组包含由给定的分隔符分隔的字符串。
_::split('foo bar baz', ' '); // ['foo', 'bar', 'baz']
第二个参数是可选的,默认值为null
,如果传递null
或空字符串作为分隔符,您将得到一个包含给定字符串中各个字符的数组。
_::split('1234'); // ['1', '2', '3', '4']
我们可以用这个做些相当酷的事情!
_::split('1234')->sum(); // 10
first
、last
、skip
、snip
以及 slice
这些函数之间关系紧密,值得牢记。
_::create([1, 2, 3, 4, 5])->first(2); // [1, 2] _::create([1, 2, 3, 4, 5])->last(2); // [4, 5] _::create([1, 2, 3, 4, 5])->skip(2); // [3, 4, 5] _::create([1, 2, 3, 4, 5])->snip(2); // [1, 2, 3] _::create([1, 2, 3, 4, 5])->slice(2, 2); // [3, 4]
贡献
请参阅 CONTRIBUTING。
致谢
本项目深受 YOLOKit 启发。对于那些在 Objective-C 中进行开发的人,我强烈建议您去看看!
许可协议
请参阅 LICENSE。