adhocore/underscore

PHP underscore受_.js启发/或克隆自_.js

v1.0.0 2022-10-02 16:34 UTC

This package is auto-updated.

Last update: 2024-09-06 09:37:24 UTC


README

PHP underscore受awesome _.js启发/或克隆。提供一组实用程序和数据操作助手,以简洁优雅的方式提供方便的功能来处理数组、列表、哈希、函数等。在处理复杂数据集时,可确保节省大量模板代码。

Latest Version Travis Build Scrutinizer CI Codecov branch StyleCI Software License Tweet Support

  • 无依赖(无供应商膨胀)。

安装

需要PHP5.6或更高版本。

composer require adhocore/underscore

用法和API

尽管它们都可以通过辅助函数underscore($data)new Ahc\Underscore($data)获得,但方法根据它们的范围按不同的层次结构和类分组和组织。这保持了其可维护性并避免了出现上帝类。

内容

Underscore

constant(mixed $value): callable

生成一个总是返回一个常量值的函数。

$fn = underscore()->constant([1, 2]);

$fn(); // [1, 2]

noop(): void

无操作!

underscore()->noop(); // void/null

random(int $min, int $max): int

返回一个介于min和max(包括)之间的随机整数。

$rand = underscore()->random(1, 10);

times(int $n, callable $fn): self

运行可调用n次并创建新集合。

$fn = function ($i) { return $i * 2; };

underscore()->times(5, $fn)->get();
// [0, 2, 4, 6, 8]

uniqueId(string $prefix): string

生成唯一ID(对于当前会话是唯一的)。

$u  = underscore()->uniqueId();      // '1'
$u1 = underscore()->uniqueId();      // '2'
$u3 = underscore()->uniqueId('id:'); // 'id:3'

UnderscoreFunction

compose(callable $fn1, callable $fn2, ...callable|null $fn3): mixed

返回一个函数列表的复合函数,每个函数都消费下一个函数的返回值。

$c = underscore()->compose('strlen', 'strtolower', 'strtoupper');

$c('aBc.xYz'); // ABC.XYZ => abc.xyz => 7

delay(callable $fn, int $wait): mixed

缓存回调的结果和给定参数,并在后续调用中重用它。

$cb = underscore()->delay(function () { echo 'OK'; }, 100);

// waits 100ms
$cb(); // 'OK'

memoize(callable $fn): mixed

返回一个可调用,当调用时,缓存给定参数的结果,并在后续调用中重用它。

$sum = underscore()->memoize(function ($a, $b) { return $a + $b; });

$sum(4, 5); // 9

// Uses memo:
$sum(4, 5); // 9

throttle(callable $fn, int $wait): mixed

返回一个可调用,它包装给定的可调用,并且可以在给定的$wait阈值内最多调用一次。

$fn = underscore()->throttle($callback, 100);

while (...) {
    $fn(); // it will be constantly called but not executed more than one in 100ms

    if (...) break;
}

UnderscoreArray

compact(): self

仅获取真实项。

underscore($array)->compact()->get();
// [1 => 'a', 4 => 2, 5 => [1]

difference(array|mixed $data): self

获取不在给定数据中的项。

underscore([1, 2, 1, 'a' => 3, 'b' => [4]])->difference([1, [4]])->get();
// [1 => 2, 'a' => 3]

findIndex(callable $fn): mixed|null

找到通过给定真值测试的第一个索引。

$u = underscore([[1, 2], 'a' => 3, 'x' => 4, 'y' => 2, 'b' => 'B']);

$isEven = function ($i) { return is_numeric($i) && $i % 2 === 0; };

$u->findIndex();        // 0
$u->findIndex($isEven); // 'x'

findLastIndex(callable $fn): mixed|null

找到通过给定真值测试的最后一个索引。

$u = underscore([[1, 2], 'a' => 3, 'x' => 4, 'y' => 2, 'b' => 'B']);

$isEven = function ($i) { return is_numeric($i) && $i % 2 === 0; };

$u->findLastIndex();        // 'b'
$u->findLastIndex($isEven); // 'y'

first(int $n): array|mixed

获取前n项。

underscore([1, 2, 3])->first(); // 1
underscore([1, 2, 3])->first(2); // [1, 2]

flatten(): self

获取多维项的扁平版本。

$u = underscore([0, 'a', '', [[1, [2]]], 'b', [[[3]], 4, 'c', underscore([5, 'd'])]]);

$u->flatten()->get(); // [0, 'a', '', 1, 2, 'b', 3, 4, 'c', 5, 'd']

indexOf(mixed $value): string|int|null

如果可用,则查找给定值的第一个索引,否则返回null。

$u = underscore([[1, 2], 'a' => 2, 'x' => 4]);

$array->indexOf(2); // 'a'

intersection(array|mixed $data): self

获取与给定数据具有共同值的项。

$u = underscore([1, 2, 'a' => 3]);

$u->intersection([2, 'a' => 3, 3])->get(); // [1 => 2, 'a' => 3]

last(int $n): array|mixed

获取最后n个元素。

underscore([1, 2, 3])->last();   // 3
underscore([1, 2, 3])->last(2);  // [2, 3]

lastIndexOf(mixed $value): string|int|null

如果存在,则找到给定值的最后一个索引,否则为null。

$u = underscore([[1, 2], 'a' => 2, 'x' => 4, 'y' => 2]);

$array->lastIndexOf(2); // 'y'

object(string|null $className): self

将项目填充到指定的类或stdClass。

underscore(['a', 'b' => 2])->object(); // stdClass(0: 'a', 'b': 2)

range(int $start, int $stop, int $step): self

从开始到结束创建一个新的范围,并使用给定的步长。

underscore()->range(4, 9)->get(); // [4, 5, 6, 7, 8, 9]

sortedIndex(mixed $object, callable|string $fn): string|int|null

获取对象应该插入的最小索引,以保持顺序。

underscore([1, 3, 5, 8, 11])->sortedIndex(9, null); // 4

union(array|mixed $data): self

获取与给定数据的项目并集/合并。

$u = underscore([1, 2, 'a' => 3]);

$u->union([3, 'a' => 4, 'b' => [5]])->get(); // [1, 2, 'a' => 4, 3, 'b' => [5]]

unique(callable|string $fn): self

使用回调函数的结果获取唯一的项目。

$u = underscore([1, 2, 'a' => 3]);

$u->union([3, 'a' => 4, 'b' => [5]])->get();
// [1, 2, 'a' => 4, 3, 'b' => [5]]

zip(array|mixed $data): self

将具有相同索引的数据和值分组在一起。

$u = underscore([1, 2, 'a' => 3, 'b' => 'B']);

$u->zip([2, 4, 'a' => 5])->get();
// [[1, 2], [2, 4], 'a' => [3, 5], 'b' => ['B', null]]

UnderscoreCollection

contains(mixed $item): bool

检查集合是否包含给定项。

$u = underscore(['a' => 1, 'b' => 2, 'c' => 3, 5]);

$u->contains(1);   // true
$u->contains('x'); // false

countBy(callable|string $fn): self

按回调函数的结果对每个组进行计数。

$u = underscore([
    ['a' => 0, 'b' => 1, 'c' => 1],
    ['a' => true, 'b' => false, 'c' => 'c'],
    ['a' => 2, 'b' => 1, 'c' => 2],
    ['a' => 1, 'b' => null, 'c' => 0],
]);

// by key 'a'
$u->countBy('a')->get();
// [0 => 1, 1 => 2, 2 => 1]

each(callable $fn): self

将给定的回调函数应用于集合中的每个项。

$answers = [];
underscore([1, 2, 3])->each(function ($num) use (&$answers) {
    $answers[] = $num * 5;
});

$answers; // [5, 10, 15]

every(callable $fn): bool

测试所有项是否通过给定的真值测试。

$gt0 = underscore([1, 2, 3, 4])->every(function ($num) { return $num > 0; });

$gt0; // true

filter(callable|string|null $fn): self

查找并返回所有通过给定真值测试的项。

$gt2 = underscore([1, 2, 4, 0, 3])->filter(function ($num) { return $num > 2; });

$gt2->values(); // [4, 3]

find(callable $fn, bool $useValue): mixed|null

找到第一个通过给定真值测试的项(或索引)。

$num = underscore([1, 2, 4, 3])->find(function ($num) { return $num > 2; });

$num; // 4

$idx = underscore([1, 2, 4, 3])->find(function ($num) { return $num > 2; }, false);

$idx; // 2

findWhere(array $props): mixed

获取包含所有给定属性的第一个项(匹配索引和值)。

$u = underscore([['a' => 1, 'b' => 2], ['a' => 2, 'b' => 2], ['a' => 1, 'b' => 3]]);

$u->findWhere(['b' => 3]); // ['a' => 1, 'b' => 3]

groupBy(callable|string $fn): self

使用回调函数的结果作为索引对项目进行分组。组中的项将保留原始索引。

$u = underscore([
    ['a' => 0, 'b' => 1, 'c' => 1],
    ['a' => true, 'b' => false, 'c' => 'c'],
    ['a' => 2, 'b' => 1, 'c' => 2],
    ['a' => 1, 'b' => null, 'c' => 0],
]);

// by key 'a'
$u->groupBy('a')->get();
// [
//  0 => [0 => ['a' => 0, 'b' => 1, 'c' => 1]],
//  1 => [1 => ['a' => true, 'b' => false, 'c' => 'c'], 3 => ['a' => 1, 'b' => null, 'c' => 0]],
//  2 => [2 => ['a' => 2, 'b' => 1, 'c' => 2]],
// ]

indexBy(callable|string $fn): self

使用回调函数的结果作为新索引重新索引项目。

$u = underscore([
    ['a' => 0, 'b' => 1, 'c' => 1],
    ['a' => true, 'b' => false, 'c' => 'c'],
    ['a' => 2, 'b' => 1, 'c' => 2],
    ['a' => 1, 'b' => null, 'c' => 0],
]);

// by key 'a'
$u->indexBy('a')->get();
// [
//   0 => ['a' => 0, 'b' => 1, 'c' => 1],
//   1 => ['a' => 1, 'b' => null, 'c' => 0],
//   2 => ['a' => 2, 'b' => 1, 'c' => 2],
// ]

invoke(callable $fn): mixed

使用所有项目作为参数调用回调函数。

$sum = underscore([1, 2, 4])->invoke(function () { return array_sum(func_get_args()); });

$sum; // 7

map(callable $fn): self

使用给定的回调函数更新每个项的值。

$map = underscore([1, 2, 3])->map(function ($num) { return $num * 2; });

$map->get(); // [2, 4, 6]

max(callable|string|null $fn): mixed

使用给定的回调函数或仅项目找到最大值。

underscore([1, 5, 4])->max(); // 5
$u = underscore([['a' => 1, 'b' => 2], ['a' => 2, 'b' => 3], ['a' => 0, 'b' => 1]]);

$u->max(function ($i) { return $i['a'] + $i['b']; }); // 5

min(callable|string|null $fn): mixed

使用给定的回调函数或仅项目找到最小值。

underscore([1, 5, 4])->min(); // 1
$u = underscore([['a' => 1, 'b' => 2], ['a' => 2, 'b' => 3], ['a' => 0, 'b' => 1]]);

$u->min(function ($i) { return $i['a'] + $i['b']; }); // 1

partition(callable|string $fn): self

将项分为两组:一组通过给定的真值测试,另一组不通过。

$u = underscore(range(1, 10));

$oddEvn = $u->partition(function ($i) { return $i % 2; });

$oddEvn->get(0); // [1, 3, 5, 7, 9]
$oddEvn->get(1); // [2, 4, 6, 8, 10]

pluck(string|int $columnKey, string|int $indexKey): self

从每个项中拉取给定的属性。

$u = underscore([['name' => 'moe', 'age' => 30], ['name' => 'curly']]);

$u->pluck('name')->get(); // ['moe', 'curly']

reduce(callable $fn, mixed $memo): mixed

使用回调函数迭代地将数组减少到单个值。

$sum = underscore([1, 2, 3])->reduce(function ($sum, $num) {
    return $num + $sum;
}, 0);

$sum; // 6

reduceRight(callable $fn, mixed $memo): mixed

与reduce相同,但首先从最右侧的项开始应用回调函数。

$concat = underscore([1, 2, 3, 4])->reduceRight(function ($concat, $num) {
    return $concat . $num;
}, '');

echo $concat; // '4321'

reject(callable $fn): self

查找并返回所有未通过给定真值测试的项。

$evens = underscore([1, 2, 3, 4, 5, 7, 6])->reject(function ($num) {
    return $num % 2 !== 0;
});

$evens->values(); // [2, 4, 6]

sample(int $n): self

以随机顺序获取最多 n 个项。

$u = underscore([1, 2, 3, 4]);

$u->sample(1)->count(); // 1
$u->sample(2)->count(); // 2

shuffle(): self

随机化项的同时保持索引不变。

underscore([1, 2, 3, 4])->shuffle()->get();

some(callable $fn): bool

测试是否有一些(至少一个)项通过给定的真值测试。

$some = underscore([1, 2, 0, 4, -1])->some(function ($num) {
    return $num > 0;
});

$some; // true

sortBy(callable $fn): self

根据给定的回调函数对项进行排序并保持索引。

$u = underscore(range(1, 15))->shuffle(); // randomize
$u->sortBy(null)->get(); // [1, 2, ... 15]

$u = underscore([['a' => 1, 'b' => 2], ['a' => 2, 'b' => 3], ['a' => 0, 'b' => 1]]);
$u->sortBy('a')->get();
// [2 => ['a' => 0, 'b' => 1], 0 => ['a' => 1, 'b' => 2], 1 => ['a' => 2, 'b' => 3]]

$u->sortBy(function ($i) { return $i['a'] + $i['b']; })->get();
// [2 => ['a' => 0, 'b' => 1], 0 => ['a' => 1, 'b' => 2], 1 => ['a' => 2, 'b' => 3]],

where(array $props): self

仅筛选包含所有给定属性的项(匹配索引和值)。

$u = underscore([['a' => 1, 'b' => 2], ['a' => 2, 'b' => 2], ['a' => 1, 'b' => 3, 'c']]);

$u->where(['a' => 1, 'b' => 2])->get(); // [['a' => 1, 'b' => 2, 'c']]

UnderscoreBase

_(array|mixed $data): self

构造函数的静态快捷方式。

$u = Ahc\Underscore\Underscore::_([1, 3, 7]);

__toString(): string

将下划线实例字符串化为 JSON 字符串。

echo (string) underscore([1, 2, 3]); // [1, 2, 3]
echo (string) underscore(['a', 2, 'c' => 3]); // {0: "a", 1: 2, "c":3}

asArray(mixed $data, bool $cast): array

获取数据作为数组。

underscore()->asArray('one');                        // ['one']
underscore()->asArray([1, 2]);                       // [1, 2]
underscore()->asArray(underscore(['a', 1, 'c', 3])); // ['a', 1, 'c', 3]

underscore()->asArray(new class {
    public function toArray()
    {
        return ['a', 'b', 'c'];
    }
}); // ['a', 'b', 'c']

underscore()->asArray(new class implements \JsonSerializable {
    public function jsonSerialize()
    {
        return ['a' => 1, 'b' => 2, 'c' => 3];
    }
}); // ['a' => 1, 'b' => 2, 'c' => 3]

clon(): self

创建自身的浅拷贝。

$u = underscore(['will', 'be', 'cloned']);

$u->clon() ==  $u; // true
$u->clon() === $u; // false

count(): int

获取项的数量。

underscore([1, 2, [3, 4]])->count(); // 3
underscore()->count();               // 0

flat(array $array): array

将多维数组展平为一维。

underscore()->flat([1, 2, [3, 4, [5, 6]]]); // [1, 2, 3, 4, 5, 6]

get(string|int|null $index): mixed

通过索引获取底层数组数据。

$u = underscore([1, 2, 3]);

$u->get();  // [1, 2, 3]
$u->get(1); // 2
$u->get(3); // 3

getData(): array

获取数据。

// same as `get()` without args:
underscore([1, 2, 3])->getData(); // [1, 2, 3]

getIterator(): \ArrayIterator

获取循环的迭代器。

$it = underscore([1, 2, 3])->getIterator();

while ($it->valid()) {
    echo $it->current();
}

invert(): self

交换所有项的索引和值。值应该是可字符串化的。

$u = underscore(['a' => 1, 'b' => 2, 'c' => 3]);

$u->invert()->get(); // [1 => 'a', 2 => 'b', 3 => 'c']

jsonSerialize(): array

获取用于 JSON 序列化的数据。

$u = underscore(['a' => 1, 'b' => 2, 'c' => 3]);

json_encode($u); // {"a":1,"b":2,"c":3}

keys(): self

获取所有键。

$u = underscore(['a' => 1, 'b' => 2, 'c' => 3, 5]);

$u->keys()->get(); // ['a', 'b', 'c', 0]

mixin(string $name, \Closure $fn): self

向实例添加自定义处理程序/方法。处理程序绑定到此实例。

Ahc\Underscore\Underscore::mixin('square', function () {
    return $this->map(function ($v) { return $v * $v; });
});

underscore([1, 2, 3])->square()->get(); // [1, 4, 9]

now(): float

当前时间的毫秒数。

underscore()->now(); // 1529996371081

omit(array|...string|...int $index): self

省略具有黑名单索引之一的项。

$u = underscore(['a' => 3, 7, 'b' => 'B', 1 => ['c', 5]]);

$u->omit('a', 0)->get(); // ['b' => 'B', 1 => ['c', 5]]

pairs(): self

将所有项配对以使用索引和值的数组。

$u = ['a' => 3, 7, 'b' => 'B'];

$u->pair(); // ['a' => ['a', 3], 0 => [0, 7], 'b' => ['b', 'B']

pick(array|...string|...int $index): self

仅选择具有白名单索引之一的项。

$u = underscore(['a' => 3, 7, 'b' => 'B', 1 => ['c', 5]]);

$u->pick(0, 1)->get(); // [7, 1 => ['c', 5]]

tap(callable $fn): self

使用克隆调用回调 fn 并返回原始 self。

$u = underscore([1, 2]);

$tap = $u->tap(function ($_) { return $_->values(); });

$tap === $u; // true

toArray(): array

将数据项转换为数组。

$u = underscore([1, 3, 5, 7]);

$u->toArray(); // [1, 3, 5, 7]

valueOf(): string

获取此实例的字符串值(JSON 表示)。

underscore(['a', 2, 'c' => 3])->valueOf(); // {0: "a", 1: 2, "c":3}

values(): self

获取所有值。

$u = underscore(['a' => 1, 'b' => 2, 'c' => 3, 5]);

$u->values()->get(); // [1, 2, 3, 5]

UnderscoreAliases

collect(callable $fn): self

map() 的别名。

detect(callable $fn, bool $useValue): mixed|null

find() 的别名。

drop(int $n): array|mixed

last() 的别名。

foldl(callable $fn, mixed $memo): mixed

reduce() 的别名。

foldr(callable $fn, mixed $memo): mixed

reduceRight() 的别名。

head(int $n): array|mixed

first() 的别名。

includes(): void

contains() 的别名。

inject(callable $fn, mixed $memo): mixed

reduce() 的别名。

select(callable|string|null $fn): self

filter() 的别名。

size(): int

count() 的别名。

tail(int $n): array|mixed

last() 的别名。

take(int $n): array|mixed

first() 的别名。

uniq(callable|string $fn): self

unique() 的别名。

without(array|mixed $data): self

difference() 的别名。

HigherOrderMessage

用于在复杂逻辑(通常封装在闭包中)上使用优雅的简写单行代码的语法糖。下面是示例。

// Higher Order Messaging
class HOM
{
    protected $n;
    public $square;

    public function __construct($n)
    {
        $this->n      = $n;
        $this->square = $n * $n;
    }

    public function even()
    {
        return $this->n % 2 === 0;
    }
}

$u = [new HOM(1), new HOM(2), new HOM(3), new HOM(4)];

// Filter `even()` items
$evens = $u->filter->even(); // 'even()' method of each items!

// Map each evens to their squares
$squares = $evens->map->square; // 'square' prop of each items!
// Gives an Underscore instance

// Get the data
$squares->get();
// [1 => 4, 3 => 16]

没有高级消息传递,如下所示

$evens = $u->filter(function ($it) {
    return $it->even();
});

$squares = $evens->map(function ($it) {
    return $it->square;
});

\ArrayAccess

Underscore 实例可以被视为数组。

$u = underscore([1, 2, 'a' => 3]);

isset($u['a']); // true
isset($u['b']); // false

echo $u[1];     // 2

$u['b'] = 'B';
isset($u['b']); // true

unset($u[1]);

Arrayizes

您可以使用此特性将所有复杂数据数组化。

use Ahc\Underscore\Arrayizes;

class Any
{
    use Arrayizes;

    public function name()
    {
        $this->asArray($data);
    }
}

许可证

MIT | © 2017-2018 | Jitendra Adhikari