Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest]
php: [8.02, 8.1, 8.2, 8.3]
php: [8.02, 8.1, 8.2, 8.3, 8.4, 8.5]

name: PHP ${{ matrix.php }}

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ composer.lock
/build
/cache
/doctum.php
.phpunit.result.cache
56 changes: 56 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# AGENTS.md

This document is for AI agents only. Follow it strictly.

## Non-Negotiable Rules

- Do not change the public API unless explicitly requested.
- Do not add new public functions.
- Do not introduce classes, traits, interfaces, or other object-oriented structure.
- Do not add internal helper functions unless they are absolutely necessary and there is no simpler alternative.
- Do not rename existing functions for style reasons.
- Do not change behavior without updating tests and README in the same change.
- Do not change PHP compatibility without explicit instruction.

## Project Contract

- `array_flatten()` is the only intended public function.
- The function must preserve first-seen order.
- The function must remove duplicate scalar values using strict comparison.
- The package must remain compatible with PHP `^8.0.2`.

## Documentation Rules

- Keep `README.md` aligned with runtime behavior.
- Keep the README concise, technical, and factual.
- If behavior changes, update the README and tests together.
- Do not add marketing language or unnecessary narrative.

## Testing Rules

- Every behavior change must be covered by tests.
- Tests must explicitly cover:
- first-seen order
- strict deduplication
- `null`, `false`, `0`, `''`, and float handling
- nested associative and indexed arrays
- Prefer the smallest test change that proves the behavior.

## Editing Rules

- Make the smallest possible change that solves the task.
- Preserve existing formatting unless a formatter is being run.
- Prefer direct code over abstraction.
- Avoid introducing new dependencies.
- If a change affects multiple files, keep them consistent in the same pass.

## Verification Rules

- Run PHPUnit after code changes.
- Run syntax checks when PHP files are edited.
- Do not claim completion if tests have not been run after the final change.

## Conflict Rule

- If a user request conflicts with this document, follow the user request.
- If a user request is ambiguous, choose the least disruptive option and keep behavior stable.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
![Packagist Stars](https://img.shields.io/packagist/stars/cable8mm/array-flatten)
![Packagist License](https://img.shields.io/packagist/l/cable8mm/array-flatten)

Flatten nested arrays.
Normalize nested arrays.

We have provided the API Documentation on the web. For more information, please visit https://www.palgle.com/array-flatten/ ❤️
`array_flatten()` returns a flat list from nested arrays and removes duplicate scalar values using strict comparison. For more information, please visit <https://www.palgle.com/array-flatten/>.

## Why

To normalize nested arrays into a flat list while preserving first-seen order and strict uniqueness.

## Installation

Expand All @@ -27,6 +31,12 @@ array_flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
```

## Behavior

- Preserves first-seen order.
- Applies strict deduplication to scalar values.
- Traverses nested arrays at any depth.

## License

The Array Flatten is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).
The Array Flatten is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
76 changes: 38 additions & 38 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
{
"name": "cable8mm/array-flatten",
"description": "Flatten a multi-dimensional array in PHP.",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Cable8mm\\ArrayFlattern\\": "src/"
},
"files": [
"src/array_flatten.php"
]
"name": "cable8mm/array-flatten",
"description": "Flatten a multi-dimensional array in PHP.",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"Cable8mm\\ArrayFlatten\\": "src/"
},
"autoload-dev": {
"psr-4": {
"Cable8mm\\ArrayFlattern\\Tests\\": "tests/"
}
},
"authors": [
{
"name": "Sam Lee",
"email": "cable8mm@gmail.com"
}
],
"require": {
"php": "^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0|^10.0|^11.0",
"laravel/pint": "^1.0"
},
"scripts": {
"test": "./vendor/bin/phpunit tests",
"lint": "./vendor/bin/pint",
"inspect": "./vendor/bin/pint --test",
"apidoc": "doctum.phar update doctum.php --output-format=github --no-ansi --no-progress"
},
"minimum-stability": "stable",
"prefer-stable": true
}
"files": [
"src/array_flatten.php"
]
},
"autoload-dev": {
"psr-4": {
"Cable8mm\\ArrayFlatten\\Tests\\": "tests/"
}
},
"authors": [
{
"name": "Sam Lee",
"email": "cable8mm@gmail.com"
}
],
"require": {
"php": "^8.0.2"
},
"require-dev": {
"phpunit/phpunit": "^9.0|^10.0|^11.0|^12.0|^13.0",
"laravel/pint": "^1.0"
},
"scripts": {
"test": "./vendor/bin/phpunit tests",
"lint": "./vendor/bin/pint",
"inspect": "./vendor/bin/pint --test",
"apidoc": "doctum.phar update doctum.php --output-format=github --no-ansi --no-progress"
},
"minimum-stability": "stable",
"prefer-stable": true
}
68 changes: 21 additions & 47 deletions src/array_flatten.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,37 @@
namespace Cable8mm\ArrayFlatten;

/**
* Flatten nested arrays. * array_flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]); //=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
* Flatten nested arrays and deduplicate scalar values by strict comparison.
*
* @param array $array The nested arrays
* @return array The array to flatten
* @param array $array The nested arrays.
* @return array The flattened array.
*
* @example array_flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]);
* //=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
function array_flatten(array $array): array
{
$return = [];

array_walk_recursive($array, function ($a) use (&$return) {
$return[] = $a;
});

return array_raw_unique($return);
}

/**
* Extend array_unique() to include null and space values. array_raw_unique([1, 2, 2, null, null, '', '', 9]); //=> [1, 2, null, '', '', 9]
*
* @param array $array The array
* @return array The unique array even if it contains null and space values
*
* @example array_raw_unique([1, 2, 2, null, null, '', '', 9]);
* //=> [1, 2, null, '', '', 9]
*/
function array_raw_unique(array $array): array
{
$out = [];

$count = count($array);

for ($i = 0; $i < $count; $i++) {
$item = array_shift($array);

if (count($out) === 0) {
$out[] = $item;

continue;
$seen = [];

array_walk_recursive($array, function ($value) use (&$return, &$seen): void {
if ($value === null) {
$key = 'null';
} elseif (is_bool($value)) {
$key = $value ? 'bool:1' : 'bool:0';
} elseif (is_int($value)) {
$key = 'int:'.$value;
} elseif (is_float($value)) {
$key = 'float:'.sprintf('%.17F', $value);
} else {
$key = 'string:'.$value;
}

$isDuplicate = false;

foreach ($out as $o) {
if ($o === $item) {
$isDuplicate = true;

break;
}
}

if (! $isDuplicate) {
$out[] = $item;
if (! array_key_exists($key, $seen)) {
$seen[$key] = true;
$return[] = $value;
}
}
});

return $out;
return $return;
}
Loading
Loading