quartet / haydn
set operation library
Installs: 47 866
Dependents: 0
Suggesters: 0
Security: 0
Stars: 9
Watchers: 8
Forks: 0
Open Issues: 2
Requires
- php: >=5.5
Requires (Dev)
- phpunit/phpunit: ~4.6
This package is not auto-updated.
Last update: 2023-07-22 11:59:04 UTC
README
配列に対してかけ算や列演算を宣言的に指定できるライブラリ。
実装の特徴として、Setに対する各種演算は単に宣言的に行われるのみで、Setオブジェクトをforeach
等でイテレーションしないかぎり、中身の走査は行われない点。
$fruits = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $drinks = [ ['name' => 'Yoghurt', 'price' => 200], ['name' => 'Soda', 'price' => 120], ['name' => 'Spirit', 'price' => 160], ]; $fruitSet = new Set(new ArraySource('fruit', $fruits, new HashKeyColumnMapper())); $drinkSet = new Set(new ArraySource('drink', $drinks, new HashKeyColumnMapper())); $fruitDrinkSet = $fruitSet->product($drinkSet); $result = $fruitDrinkSet->toArray();
Install
composer require quartet/haydn
Usage
Set declaration (using source object)
$fruitsAssoc = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $fruitsSet = new Set(new ArraySource('fruit', $fruitsAssoc, new HashKeyColumnMapper()); foreach ($fruitSet as $fruit) { echo 'name:' . $fruit['name'] . ' price:' . $fruit['price'] . PHP_EOL; }
Specific Sets
IdenticalSet
$fruitsAssoc = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $fruitsSet = new Set(new ArraySource('fruit', $fruitsAssoc, new HashKeyColumnMapper()); $identicalSet = new IdenticalSet(); $all = $fruitSet->product($identicalSet); // same as $fruitSet $all = $identicalSet->product($fruitSet); // same as $fruitSet $all = $fruitSet->union($identicalSet); // same as $fruitSet $all = $identicalSet->union($fruitSet); // same as $fruitSet
EmptySet
$fruitsAssoc = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $fruitsSet = new Set(new ArraySource('fruit', $fruitsAssoc, new HashKeyColumnMapper()); $emptySet = new EmptySet(); $all = $fruitSet->product($emptySet); // empty $all = $emptySet->product($fruitSet); // empty $all = $fruitSet->union($emptySet); // same as $fruitSet $all = $emptySet->union($fruitSet); // same as $fruitSet
Set operations
ProductSet
Set#product(Set $target)
2つのSetをかけたSetを作る。(デカルト積)
$fruits = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $drinks = [ ['name' => 'Yoghurt', 'price' => 200], ['name' => 'Soda', 'price' => 120], ['name' => 'Spirit', 'price' => 160], ]; $fruitSet = new Set(new ArraySource('fruit', $fruits, new HashKeyColumnMapper())); $drinkSet = new Set(new ArraySource('drink', $drinks, new HashKeyColumnMapper())); $fruitDrinkSet = $fruitSet->product($drinkSet);
SelectSet
Set#select(array $selectors)
Setの各要素に対して、何らかの加工を加えた結果のSet。
- 列の選択
- 列の値の演算 − 複数行への分割
$fruits = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $fruitMenuSet = new Set(new ArraySource('fruit', $fruits, new HashKeyColumnMapper())) ->select([function($row) { return [ 'menu item name' => $row['name'] ]; }]); ;
FilterSet
Set#filter(MatcherInterface $matcher)
Setの要素に対して、マッチしたものだけを取り出したSet。
$products = [ ['name' => 'Apple', 'price' => 100, 'type' => 'fruit'], ['name' => 'Yoghurt', 'price' => 200, 'type' => 'drink'], ['name' => 'Soda', 'price' => 120, 'type' => 'drink'], ['name' => 'Banana', 'price' => 80, 'type' => 'fruit'], ['name' => 'Spirit', 'price' => 160, 'type' => 'drink'], ]; $fruitSet = new Set(new ArraySource('product', $products, new HashKeyColumnMapper())) ->filter(new Matcher(['type' => 'fruit'])); ;
Matcherは、対象列の名前をキーとして、完全一致する文字列を指定する。 また、完全一致の値ではなく、Closureを渡して動的に評価させることも可能。
new Matcher(['type' => function($value) { return strpos($value, ':') !== false; }])
Devide
Set#devide(array $matchers)
Matcherを複数指定して、それぞれのMatcherに対応するSetへ分割する。
$products = [ ['name' => 'Apple', 'price' => 100, 'type' => 'fruit'], ['name' => 'Yoghurt', 'price' => 200, 'type' => 'drink'], ['name' => 'Soda', 'price' => 120, 'type' => 'drink'], ['name' => 'Banana', 'price' => 80, 'type' => 'fruit'], ['name' => 'Spirit', 'price' => 160, 'type' => 'drink'], ]; $productSet = new Set(new ArraySource('product', $products, new HashKeyColumnMapper())); list($fruitSet, $drinkSet) = $productSet->devide([ 'fruit' => new Matcher(['type' => 'fruit']), 'drink' => new Matcher(['type' => 'drink']), ]);
Union
Set#union(Set $target)
複数のSetを結合して、つながったSetを返す。
$fruits = [ ['name' => 'Apple', 'price' => 100], ['name' => 'Banana', 'price' => 80], ]; $drinks = [ ['name' => 'Yoghurt', 'price' => 200], ['name' => 'Soda', 'price' => 120], ['name' => 'Spirit', 'price' => 160], ]; $fruitSet = new Set(new ArraySource('fruit', $fruits, new HashKeyColumnMapper())); $drinkSet = new Set(new ArraySource('drink', $drinks, new HashKeyColumnMapper())); $allSet = $fruitSet->union($drinkSet);
Grouping
グルーピング演算したSetを返す。ここでグルーピング演算とは、キーとなる集合の各要素それぞれがさらに明細の集合を有するような、「キーの数だけグループを持つ集合」を作成することを指す。 具体的には以下のとおり。
- キー集合Aがあり、
- Aの各要素a1,a2,a3,...ぞれに対して明細集合B1,B2,B3,...を作成したい場合に、
- Aのある要素anを以下のような行に展開し、それをa1,a2,a3,...すべてに適用する
- ヘッダー行(anグループの先頭を宣言する行)
- 明細集合Bnの各行
- フッター行(anグループの末尾を宣言する行)
$k1 = new Set(new SingleColumnArraySource('k1', ['あいう', 'かきく'])); $k2 = new Set(new SingleColumnArraySource('k2', ['abc', 'def'])); $k3 = new Set(new SingleColumnArraySource('k3', ['123', '456'])); $g1 = new Set\GroupingSet( // Key Set $k1->product($k2), // Header Generator function ($r) { return ['type' => 'header', 'name' => $r['k1'] . '-' . $r['k2']]; }, // Detail Set Generator function ($r) use ($k3) { $set = new Set(new SingleRowSource('k1k2', $r)); $resultSet = $set->product($k3)->select([function ($r) { return [ 'type' => 'detail', 'content' => $r['k1'] . ' ' . $r['k2'] . ' ' . $r['k3'], ]; }]); return $resultSet; }, // Footer Generator null ); $all = $g1->toArray(); var_dump($all); // [ // 'type' => 'header', // 'name' => 'あいう-abc', // ], [ // 'type' => 'detail', // 'content' => 'あいう abc 123', // ], [ // 'type' => 'detail', // 'content' => 'あいう abc 456', // ], [ // 'type' => 'header', // 'name' => 'あいう-def', // ], [ // 'type' => 'detail', // 'content' => 'あいう def 123', // ], [ // 'type' => 'detail', // 'content' => 'あいう def 456', // ], [ // 'type' => 'header', // 'name' => 'かきく-abc', // ], [ // 'type' => 'detail', // 'content' => 'かきく abc 123', // ], [ // 'type' => 'detail', // 'content' => 'かきく abc 456', // ], [ // 'type' => 'header', // 'name' => 'かきく-def', // ], [ // 'type' => 'detail', // 'content' => 'かきく def 123', // ], [ // 'type' => 'detail', // 'content' => 'かきく def 456', // ],
Source
Setのデータ供給源(データソース)。
- ArraySource
- SingleColumnArraySource
- SingleRowSource
ArraySource
PHPの配列(2次元)をデータソースとして利用する。
$fruitArray = [ ['id' => 1, 'name' => 'Apple'], ['id' => 2, 'name' => 'Banana'], ['id' => 3, 'name' => 'Lemon'], ]; $fruitSet = new Set(new ArraySource('fruit', $fruitArray, new HashKeyColumnMapper())); $output = $fruitSet->toArray(); var_dump($output); // ['id' => 1, 'name' => 'Apple'], // ['id' => 2, 'name' => 'Banana'], // ['id' => 3, 'name' => 'Lemon']
SingleColumnArraySource
1列のみのPHP配列(1次元)をデータソースとして利用する。
$fruitArray = [ 'Apple', 'Banana', 'Lemon']; $fruitSet = new Set(new SingleColumnArraySource('fruit', $fruitArray, new NullColumnMapper())); $output = $fruitSet->toArray(); var_dump($output); // ['fruit' => 'Apple'], // ['fruit' => 'Banana'], // ['fruit' => 'Lemon'],
SingleRowSource
1行のみのPHP配列(1次元)をデータソースとして利用する。
$fruitArray = ['1','Apple','140']; $fruitSet = new Set(new SingleRowSource('fruit', $fruitArray, new SimpleArrayColumnMapper([ 'id', 'name', 'price' ]))); $output = $fruitSet->toArray(); var_dump($output); // ['id'=>1, 'name' => 'Apple', 'price'=>140],
ColumnMapper
Sourceの列名マッピング
- HashKeyColumnMapper
- SimpleArrayColumnMapper
- NullColumnMapper
- ChainMapper
HashKeyColumnMapper
各行が連想配列になっているデータソースで、連想配列のキー名をそのまま列名として使う。
$fruitArray = [ ['id' => 1, 'name' => 'Apple'], ['id' => 2, 'name' => 'Banana'], ['id' => 3, 'name' => 'Lemon'], ]; $fruitSet = new Set(new ArraySource('fruit', $fruitArray, new HashKeyColumnMapper())); $output = $fruitSet->toArray(); var_dump($output); // ['id' => 1, 'name' => 'Apple'], // ['id' => 2, 'name' => 'Banana'], // ['id' => 3, 'name' => 'Lemon']
SimpleArrayColumnMapper
キーの無い配列データソースに、列名を配列で与える。
$fruitColumn = ['id', 'name']; $fruitArray = [ [1, 'Apple'], [2, 'Banana'], [3, 'Lemon'], ]; $fruitSet = new Set(new ArraySource('fruit', $fruitArray, new SimpleArrayColumnMapper($fruitColumn))); $output = $fruitSet->toArray(); var_dump($output); // ['id' => 1, 'name' => 'Apple'], // ['id' => 2, 'name' => 'Banana'], // ['id' => 3, 'name' => 'Lemon']
NullColumnMapper
列名マップを使わない。
$fruitArray = [ [1, 'Apple'], [2, 'Banana'], [3, 'Lemon'], ]; $fruitSet = new Set(new ArraySource('fruit', $fruitArray, new NullColumnMapper())); $output = $fruitSet->toArray(); var_dump($output); // [0 => 1, 1 => 'Apple'], // [0 => 2, 1 => 'Banana'], // [0 => 3, 1 => 'Lemon']
ChainMapper
列名マッパーを複数チェインさせる。
Support
If you find a bug or have a question, or want to request a feature, create an issue or pull request for it on Issues.
Copyright
Copyright (c) 2015 GOTO Hidenori, All rights reserved.