dseguy/data-combinator

数据组合器是一个PHP库,用于组合数据。

v0.6.11 2021-05-11 15:41 UTC

README

当你想要列出各种数据列表的所有可能的组合时。

例如,从 [[1, 2], [3, 4]]

[
	[1, 3], 
	[1, 4],
	[2, 3], 
	[2, 4],
] 

此组件允许您通过将每个可能的值与其他值组合来创建大型数据集。

应用场景

  • 为命令行工具生成所有可能的组合
  • 为传入数据生成所有变体
  • 生成结构化数据

安装

使用 Composer,执行永恒的操作

$ composer require dseguy/data-combinator

简单示例

require 'vendor/autoload.php';

use Datacombinator\Matrix;

$m = new Datacombinator\Matrix();
$m->addSet('x', [1,2,3]);
$m->addSet('y', [4,5,6]);

foreach($m as $value) {
    print_r($value);
}

这会生成1、2、3与4、5、6的所有组合,总共9个数组。

(
    [x] => 1
    [y] => 4
)
Array
(
    [x] => 1
    [y] => 5
)
Array
(
    [x] => 1
    [y] => 6
)
... 
Array
(
    [x] => 3
    [y] => 6
)

APIs

常见行为

公共方法至少需要两个参数;值的名称和实际值或值的生成器。

每个值名称是一个字符串或null。当名称为null时,会自动生成id,从0开始(类似于PHP)。

数组的索引可以用字符串提供,该字符串将被PHP转换为数组索引。使用null和Matrix::TYPE_ARRAY与使用Matrix::TYPE_LIST具有相同的效果。使用Matrix::TYPE_LIST与命名值是合法的:在生成时,名称将被丢弃,但在配置时提供了一些可读性。

可以通过再次添加来覆盖之前设置的属性。

建议避免使用除字符串、字符串中的整数和null以外的任何格式。

addConstant

这向矩阵添加一个唯一值。此值不会有重复。请注意,该值可能是一个数组。

$m = new Datacombinator\Matrix();
$m->addConstant('x', 2);
$m->addConstant('y', 3);

Array
(
    [x] => 2
    [y] => 3
)

有关克隆对象的更多信息,请参阅 addCopy()

generate

返回一个用于foreach()结构的生成器。

生成器将返回与toArray()方法相同的值,但一个接一个地产生。完整生成后,generate()方法将再次根据缓存产生相同的值。

$m = new Datacombinator\Matrix();
$m->addSet('x', [1, [2], 3]);
$m->addConstant('y', 4);

foreach($m->generate() as $array) {
    print_r($array);
}

addSet

此操作将值列表添加到矩阵中。每个值将被重复一次。提供数组数组的数组,以合并这些数组。

$m = new Datacombinator\Matrix();
$m->addSet('x', [1, [2], 3]);
$m->addConstant('y', 4);

(
    [x] => 1
    [y] => 4
)
Array
(
    [x] => Array (
            2
            )
    [y] => 4
)
Array
(
    [x] => 3
    [y] => 4
)

addLambda

此方法将闭包、回调函数或箭头函数作为值添加。闭包将针对每个项目调用以生成新值。

闭包可以是常量或动态的。第一个仅在计算一次后总是相同的(例如,今天的日期)。第二个每次计算,并可能产生不同的值(例如,rand()值或依赖于先前生成值的闭包)。

闭包接收一个包含所有先前创建值的(数组)参数。这样,它可以基于先前生成的值创建新值。该数组按添加到矩阵的顺序填充:特别是,这意味着并非所有值都始终可用,因为其中一些值可能仍在等待。此外,作为“别名”添加的值将在最后处理,且不可用。

提供的参数是一个数组。其值的类型与添加到矩阵中的值的类型相同。对于子矩阵,它可能是一个数组或对象,具体取决于配置。

当使用闭包或箭头函数时,可以通过$this->uniqueId属性访问唯一标识符。uniqueId是一个从1开始的int,每次使用时递增。

$m = new Datacombinator\Matrix();

// No argument for this closure, as we don't need it
$m->addLambda('x', function () { return rand(0, 10);});

// This closure takes the previously created values as input
// the range of random values is now twice as large
$m->addLambda('y', function ($value) { return rand(0, 2 * $value['x']);});

// the closure are called each time once, so this matrix as one element, with 2 closure calls
(
    [x] => 4
    [y] => 7
)

$m = new Matrix();

// No argument for this closure, as we don't need it
$m->addLambda('x', function () { return $this->uniqueId;});
$m->addSet('y', [5,6]);

(
    [x] => 1
    [y] => 5
)
(
    [x] => 2
    [y] => 6
)
$m = new Datacombinator\Matrix();

// No argument for this closure, as we don't need it
$a = $m->addConstant('a', 'A');
$m->addAlias('b', $a);
$m->addLambda('x', function ($r) { return $r['a'].($r['b'] ?? 'No B').($r['c'] ?? 'No C')});
$m->addConstant('c', 'C');

print_r($m->toArray());

Array
(
    [0] => Array
        (
            [a] => A
            // No B, because it is an alias
            // No C, because it is defined later. It may be moved before 'x' to get access to it
            [x] => ANo BNo C
            [c] => C
            [b] => A
        )

)

addPermute

使用列表作为单个参数,并生成其中所有值的所有可能排列。

$m = new Datacombinator\Matrix();

// Create all permutation in the list : total 6 of them
$m->addPermute('x', [1, 2, 3]);


(
    [x] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

)
Array
(
    [x] => Array
        (
            [0] => 1
            [1] => 3
            [2] => 2
        )

)
Array
(
    [x] => Array
        (
            [0] => 2
            [1] => 1
            [2] => 3
        )

)
Array
(
    [x] => Array
        (
            [0] => 2
            [1] => 3
            [2] => 1
        )

)
Array
(
    [x] => Array
        (
            [0] => 3
            [1] => 1
            [2] => 2
        )

)
Array
(
    [x] => Array
        (
            [0] => 3
            [1] => 2
            [2] => 1
        )

)

addCombine

使用列表作为单个集合,并生成它们的所有可能组合,从空数组(无)到所有元素。

$m = new Datacombinator\Matrix();

// Create all combinaisons from the list : total 8 of them
$m->addCombine('x', [1, 2, 3]);


(
    [x] => Array
        (
        )

)
Array
(
    [x] => Array
        (
            [0] => 1
        )

)
Array
(
    [x] => Array
        (
            [0] => 2
        )

)
Array
(
    [x] => Array
        (
            [0] => 1
            [1] => 2
        )

)
Array
(
    [x] => Array
        (
            [0] => 3
        )

)
Array
(
    [x] => Array
        (
            [0] => 1
            [1] => 3
        )

)
Array
(
    [x] => Array
        (
            [0] => 2
            [1] => 3
        )

)
Array
(
    [x] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
        )

)

addCopy

addConstant()创建常量的值副本不同,addCopy每次都克隆输入对象。它们在生成时看起来相同,但实际上是不同的对象。

$m = new Datacombinator\Matrix();

// Create all combinaisons from the list : total 8 of them
$m->addClone('x', new \stdClass);
$m->addSet('i', [1, 2]);

$generated = $m->toArray();

addMatrix

将矩阵添加到另一个矩阵是嵌套矩阵的方式。它还允许通过组合过程创建对象。

$m = new Datacombinator\Matrix();
$m->addSet('i', [2, 3]);
$m->setClass(stdClass::class);

$n = new Datacombinator\Matrix();
$n->addSet('j', [5,7]);
$n->addMatrix('x', $m);
Array
(
    [j] => 5
    [x] => stdClass Object
        (
            [i] => 2
        )

)
Array
(
    [j] => 5
    [x] => stdClass Object
        (
            [i] => 3
        )

)
Array
(
    [j] => 7
    [x] => stdClass Object
        (
            [i] => 2
        )

)
Array
(
    [j] => 7
    [x] => stdClass Object
        (
            [i] => 3
        )

)

矩阵有两个选项

  • 缓存,在生成值后将其缓存。
    • Matrix::WITHOUT_CACHE每次都重新生成矩阵,
    • Matrix::WITH_CACHE生成缓存一次,并在以后重用。
  • 写入模式,它配置了多重定义的情况下的行为
    • Matrix::OVERWRITE是默认值。值被新的定义替换。
    • Matrix::SKIP跳过任何先前定义的值
    • Matrix::WARN在重用先前定义的名称时抛出异常。

addAlias

在生成的数据中的另一个槽位重复使用先前生成的值。这在需要将相同值设置在两个(或更多)槽位时非常有用。

$m = new Matrix();
$i = $m->addSet('i', [2, 3]);
$m->addAlias('j', $i);

print_r($m->toArray());

Array
(
    [0] => Array
        (
            [i] => 2
            [j] => 2
        )

    [1] => Array
        (
            [i] => 3
            [j] => 3
        )

)

别名可以以任何顺序添加:可以从顶层矩阵或反过来从子矩阵中调用在子矩阵中创建的别名。

别名作为矩阵中的最后元素处理。它们可能在Lambda调用中不可用,Lambda调用总是先发生。

addSequence

生成从最小值到最大值的顺序数据,可选地由闭包更新。

$m = new Matrix();
$i = $m->addSequence('i', 0, 10);

print_r($m->toArray());

Array
(
    [0] => Array
        (
            [i] => 0
        )
    [1] => Array
        (
            [i] => 1
        )
    [2] => Array
        (
            [i] => 2
        )
// ....
    [9] => Array
        (
            [i] => 9
        )
)

setClass

默认情况下,矩阵生成数组类型的值。这是最灵活的格式。

可以将这些数组转换为对象,通过提供一个类,或使用Matrix::TYPE_LIST常量将其转换为列表(自动索引的数组)。可以使用Matrix::TYPE_ARRAY常量强制使用默认类型。

对象通过不带参数的实例化创建。然后,通过公共访问设置公共属性。省略私有和受保护的属性;未设置值保持不变;也省略额外的值。

class Point {
	int $x, $y;
}

$m = new Datacombinator\Matrix();
$m->setClass(Point::class);
$m->addSet('x', [1,2]);
$m->addSet('y', [4,5]);

Point Object
(
    [x] => 1
    [y] => 4
)

您也可以通过使用其完全限定名称来获取一个stdClass对象。然后,所有传递的值都将转换为属性。

class Point {
	int $x, $y;
}

$m = new Datacombinator\Matrix();
$m->setClass(\stdClass::class);
$m->addConstant('x', 1);
$m->addConstant('y', 2);

stdClass Object
(
    [x] => 1
    [y] => 2
)

count

计算要生成的元素数量。

$m = new Datacombinator\Matrix();
$m->addSet('x', [1,2]);
$m->addSet('y', [4,5]);
print $m->count()." elements";


// 4 elements

toArray

以数组形式返回所有可能的组合

$m = new Datacombinator\Matrix();
$m->addSet('x', [1,2]);
$m->addSet('y', [4,5]);
print_r($m->toArray());

Array
(
    [0] => Array
        (
            [x] => 1
            [y] => 4
        )

    [1] => Array
        (
            [x] => 1
            [y] => 5
        )

    [2] => Array
        (
            [x] => 2
            [y] => 4
        )

    [3] => Array
        (
            [x] => 2
            [y] => 5
        )

)

常见问题解答(FAQ)

如何打乱结果顺序?

使用toArray()方法,并对其应用PHP原生的shuffle()函数。

如何限制结果数量?

使用foreach()与generate()方法结合,计算所需元素的个数。然后在所有所需结果生成后停止。