Skip to content

Commit

Permalink
Merge pull request #15 from Hi-Folks/feat/group-by
Browse files Browse the repository at this point in the history
The groupBy() method
  • Loading branch information
roberto-butti authored Jul 11, 2024
2 parents a0a7d30 + c417ca7 commit 704882c
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.3.6 - 2024-07-11
- Implementing the `groupBy()` method

## 0.3.5 - 2024-07-07
- Fix returning nested array type after `where()`

Expand Down
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,45 @@ Array
)
*/
```

### The `groupBy()` method

Groups the elements of the `Block` object by a specified field.

This method takes a field name as an argument and groups the elements of the `Block` object based on the values of that field. Each element is grouped into an associative array where the keys are the values of the specified field and the values are arrays of elements that share that key.

```php
use HiFolks\DataType\Block;
$data = Block::make([
['type' => 'fruit', 'name' => 'apple'],
['type' => 'fruit', 'name' => 'banana'],
['type' => 'vegetable', 'name' => 'carrot'],
]);
$grouped = $data->groupBy('type');
$grouped->dumpJson();
/*
{
"fruit": [
{
"type": "fruit",
"name": "apple"
},
{
"type": "fruit",
"name": "banana"
}
],
"vegetable": [
{
"type": "vegetable",
"name": "carrot"
}
]
}
*/
```


## Looping Data
The Block class implements the Iterator interface.
While looping an array via Block, by default, if the current element should be an array, a Block is returned so that you can access the Block method for handling the current array item in the loop.
Expand Down
42 changes: 42 additions & 0 deletions src/Traits/QueryableBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,46 @@ public function select(int|string ...$columns): self
return $table;
}

/**
* Groups the elements of the Block by a specified field.
*
* This method takes a field name as an argument and groups the elements of the
* Block object based on the values of that field. Each element is grouped into
* an associative array where the keys are the values of the specified field
* and the values are arrays of elements that share that key.
*
* @param string|int $field The field name to group by.
* @return self A new Block instance with the grouped elements.
*
*/
public function groupBy(string|int $field): self
{
$result = [];

foreach ($this as $value) {
$property = $value->get($field);
$property = self::castVariableForStrval($property);
if (!$property) {
continue;
}
if (! array_key_exists(strval($property), $result)) {
$result[$property] = [];
}
$result[$property][] = $value->toArray();
}

return self::make($result);
}

private static function castVariableForStrval(mixed $property): bool|float|int|string|null
{
return match(gettype($property)) {
'boolean' => $property,
'double' => $property,
'integer' => $property,
'string' => $property,
default => null,
};
}

}
13 changes: 13 additions & 0 deletions tests/Unit/BidimensionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,19 @@ function () use ($dataTable): void {
},
);

test(
'group by',
function () use ($dataTable): void {
$table = Block::make($dataTable);
$grouped = $table->groupBy("product");
expect($grouped->getBlock("Door"))->tohaveCount(2);
expect($grouped->getBlock("Desk"))->tohaveCount(1);
expect($grouped->getBlock("NotExists"))->tohaveCount(0);

},
);


test(
'extract json by attribute',
function (): void {
Expand Down
28 changes: 28 additions & 0 deletions tests/Unit/Traits/QueryableBlockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,31 @@ function () use ($fruitsArray): void {

},
);

test(
'group by',
function () use ($fruitsArray): void {
$table = Block::make($fruitsArray);
$grouped = $table->groupBy("color");
expect($grouped->getBlock("red"))->tohaveCount(2);
expect($grouped->getBlock("yellow"))->tohaveCount(1);
expect($grouped->getBlock("NotExists"))->tohaveCount(0);

},
);

test(
'group by 2',
function (): void {
$data = Block::make([
['type' => 'fruit', 'name' => 'apple'],
['type' => 'fruit', 'name' => 'banana'],
['type' => 'vegetable', 'name' => 'carrot'],
]);
$grouped = $data->groupBy('type');
expect($grouped->getBlock("fruit"))->tohaveCount(2);
expect($grouped->getBlock("vegetable"))->tohaveCount(1);
expect($grouped->getBlock("NotExists"))->tohaveCount(0);

},
);

0 comments on commit 704882c

Please sign in to comment.