ibsciss/php-functional

PHP中的reducer实现

dev-master / 1.0.x-dev 2016-03-17 21:43 UTC

This package is not auto-updated.

Last update: 2024-09-26 00:14:39 UTC


README

Join the chat at https://gitter.im/Ibsciss/php-functional

Software License Travis CI Code Coverage Scrutinizer Code Quality Build Status

收集一系列函数和类,为您的项目提供一些简洁、一致且经过良好测试的函数式工具。

特别适合轻松构建数据处理算法。

安装

通过Composer

$ composer require ibsciss/php-functionnal

用法

简单示例

想象你想计算10月份的增值税总额

而不是这样做

function compute_october_vat() {
    $total_vat_amount = 0;
    foreach ($invoices as $invoice) {
        if ($invoice->due_date->format('m') == '10') {
            $total_vat_amount += $invoice->amount * 0.2;
        }
    }
    return $total_vat_amount;
}

或者,如果你想尝试使用map / reduce函数

function compute_october_vat() {
    return array_reduce(
        array_map(
         function($invoice) { return $invoice->amount * 0.2; },
         array_filter( $invoices, function($invoice) { return $invoice->due_date->format('m') == '10'; } )
        ),
        function($x, $y) { return $x + $y; }, 0);
}

你现在可以使用更流畅的API

function compute_october_vat() {
    return Fp\collection($invoices)
        ->filter( function($invoice) { return $invoice->due_date->format('m') == '10'; }; )
        ->map( function($invoice) { return $invoice->amount * 0.2; }; )
        ->add();
}

函数式助手

组合

组合函数允许您从现有函数创建新函数

compose(f,g,h)(x) == f(g(h(x)))

一个实用示例

$plus_one = function($x) { return $x + 1; };
$square = function($x) { return pow($x, 2); };

$plus_one_and_square = Fp\compose($plus_one, $square);
$plus_one_and_square(2) //return 9

当然你可以组合尽可能多的函数。

管道函数

管道函数有助于对集合应用转换,Martin Fowler写了一篇非常好的介绍(基于ruby)关于它。在同一博客上,你还可以找到其他资源来学习如何使用管道重构过多的循环

mapfilterreduce函数是围绕本地PHP函数包装的,要了解我们为什么要这样做,请参阅常见问题解答

Map

将函数应用于集合中的每个项以创建一个新数组。

//square each item of the collection
Fp\map(
  function($x) {
    return pow($x, 2); //square function
  }, [1,2,3]
); //return [1,4,9,16]

Filter

构建一个数组,其中包含在给定的回调中返回true的项。

//return even values from the collection
Fp\filter(
  function($x) {
    return ($x % 2 == 0);
  },
  [1,2,3,4]
); //return [2,4]

Reduce

通过将每个项传递给给定的回调来累积。回调返回的值用于下一次调用(第一次调用提供一个初始值)。

//sum values of the collection
Fp\reduce(
  function($carry, $item) {
    return $carray + $item
  },
  [1,2,3,4],
  0
); //return 10

链式调用

您可以通过使用Fp\collection(collection)函数来链式操作(不要忘记调用values()以获取结果)

//squared even values from the given collection
Fp\collection([1,2,3,4])
  ->filter(
    function($x) { return ($x % 2 == 0); }
  )
  ->map(
    function($x) { return pow($x, 2); }
  )
  ->values();  

集合转换器

使用传统的管道函数,您必须迭代整个集合的每个转换步骤,并创建一个中间集合,这在内存使用上是一个巨大的浪费。

此外,您无法真正提取一个步骤以在其他上下文中使用它,这不利于代码重用。

为了克服传统管道函数的这些缺点,函数式世界带来了一种很好的解决方案:转换器

映射

类似于map

过滤

类似filter

标量转换器

single_result终端reducer一起使用。

First

返回第一个元素

Max

返回最大值

聚合reducer

批处理

批处理结果

枚举

创建带有结果的索引元组

终端reducer

追加

追加到数组

连接

通过合并实现的不可变追加

single_result

获取标量结果而不是集合

常见问题解答

为什么不直接使用array_*(array_filter、array_map)函数?

  • 为了提高API一致性
  • 能够在没有省略可迭代对象的情况下产生转换器
  • 能够消费Collection对象。

变更日志

请参阅变更日志以获取有关最近更改的更多信息。

测试

$ composer test

贡献

请参阅CONTRIBUTING以获取详细信息。

安全

如果您发现任何与安全相关的问题,请通过电子邮件:author_email联系,而不是使用问题跟踪器。

致谢

许可证

MIT许可证(MIT)。请参阅许可证文件以获取更多信息。