├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── config.yml └── workflows │ ├── run-tests.yml │ └── php-cs-fixer.yml ├── composer.json ├── LICENSE.md ├── CHANGELOG.md ├── .php-cs-fixer.dist.php ├── src └── array_functions.php └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: spatie 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Feature Request 4 | url: https://github.com/spatie/array-functions/discussions/new?category=ideas 5 | about: Share ideas for new features 6 | - name: Ask a Question 7 | url: https://github.com/spatie/array-functions/discussions/new?category=q-a 8 | about: Ask the community for help 9 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | test: 9 | runs-on: ${{ matrix.os }} 10 | 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | os: [ubuntu-latest] 15 | php: [7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5] 16 | dependency-version: [prefer-stable] 17 | 18 | name: P${{ matrix.php }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} 19 | 20 | steps: 21 | - name: Checkout code 22 | uses: actions/checkout@v6 23 | 24 | - name: Setup PHP 25 | uses: shivammathur/setup-php@v2 26 | with: 27 | php-version: ${{ matrix.php }} 28 | coverage: none 29 | 30 | - name: Install dependencies 31 | run: composer update --no-interaction --prefer-source 32 | 33 | - name: Execute tests 34 | run: vendor/bin/phpunit 35 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spatie/array-functions", 3 | "description": "Some handy array helpers", 4 | "keywords": [ 5 | "spatie", 6 | "array", 7 | "helper", 8 | "handy" 9 | ], 10 | "homepage": "https://github.com/spatie/array-functions", 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Freek Van der Herten", 15 | "email": "freek@spatie.be", 16 | "homepage": "https://murze.be", 17 | "role": "Developer" 18 | } 19 | ], 20 | "require": { 21 | "php": "^7.4|^8.0" 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "^9.6" 25 | }, 26 | "autoload": { 27 | "files": [ 28 | "src/array_functions.php" 29 | ] 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Spatie\\Test\\": "tests" 34 | } 35 | }, 36 | "scripts": { 37 | "test": "phpunit" 38 | } 39 | } -------------------------------------------------------------------------------- /.github/workflows/php-cs-fixer.yml: -------------------------------------------------------------------------------- 1 | name: Code style 2 | 3 | on: [push] 4 | 5 | jobs: 6 | style: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout code 11 | uses: actions/checkout@v6 12 | 13 | - name: Fix style 14 | uses: docker://oskarstark/php-cs-fixer-ga 15 | with: 16 | args: --config=.php-cs-fixer.dist.php --allow-risky=yes 17 | 18 | - name: Extract branch name 19 | shell: bash 20 | run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" 21 | id: extract_branch 22 | 23 | - name: Commit changes 24 | uses: stefanzweifel/git-auto-commit-action@v2.3.0 25 | with: 26 | commit_message: Fix styling 27 | branch: ${{ steps.extract_branch.outputs.branch }} 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Freek Van der Herten 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `array-functions` will be documented in this file 4 | 5 | ## 1.9.3 - 2021-04-03 6 | 7 | - test enhancement and integrate GitHub Actions (#22) 8 | 9 | ## 1.9.2 - 2020-03-31 10 | 11 | - optimize array_rand_weighted (#19) 12 | 13 | ## 1.9.1 - 2019-10-14 14 | 15 | - fix division by zero in `array_split` (#16) 16 | 17 | ## 1.9.0 - 2019-10-05 18 | 19 | - performance improvements 20 | - drop support for PHP 7.1 and below 21 | 22 | ## 1.8.0 - 2016-03-08 23 | 24 | ### Added 25 | - array_flatten function 26 | 27 | ## 1.7.0 - 2015-11-18 28 | 29 | ### Added 30 | - array_merge_values function 31 | 32 | ## 1.6.0 - 2015-10-28 33 | 34 | ### Added 35 | - array_split function 36 | 37 | ## 1.5.0 - 2015-06-29 38 | 39 | ### Added 40 | - array_split_filter function 41 | 42 | ## 1.4.0 - 2015-06-29 43 | 44 | ### Added 45 | - array_rand_value now can return multiple values (like array_rand) 46 | 47 | ## 1.3.0 - 2015-06-24 48 | 49 | ### Added 50 | - array_rand_weighted function 51 | - array_keys_exist function 52 | 53 | ## 1.2.0 - 2015-06-22 54 | 55 | ### Changed 56 | - Various fixes & improvements 57 | 58 | ## 1.1.0 - 2015-05-11 59 | 60 | ### Added 61 | - values_in_array function 62 | 63 | ## 1.0.0 - 2015-05-10 64 | 65 | ### Added 66 | - Everything, initial release 67 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | notPath('bootstrap/*') 5 | ->notPath('storage/*') 6 | ->notPath('resources/view/mail/*') 7 | ->in([ 8 | __DIR__ . '/src', 9 | __DIR__ . '/tests', 10 | ]) 11 | ->name('*.php') 12 | ->notName('*.blade.php') 13 | ->ignoreDotFiles(true) 14 | ->ignoreVCS(true); 15 | 16 | return (new PhpCsFixer\Config) 17 | ->setRules([ 18 | '@PSR2' => true, 19 | 'array_syntax' => ['syntax' => 'short'], 20 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 21 | 'no_unused_imports' => true, 22 | 'not_operator_with_successor_space' => true, 23 | 'trailing_comma_in_multiline' => true, 24 | 'phpdoc_scalar' => true, 25 | 'unary_operator_spaces' => true, 26 | 'binary_operator_spaces' => true, 27 | 'blank_line_before_statement' => [ 28 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 29 | ], 30 | 'phpdoc_single_line_var_spacing' => true, 31 | 'phpdoc_var_without_name' => true, 32 | 'method_argument_space' => [ 33 | 'on_multiline' => 'ensure_fully_multiline', 34 | 'keep_multiple_spaces_after_comma' => true, 35 | ] 36 | ]) 37 | ->setFinder($finder); 38 | -------------------------------------------------------------------------------- /src/array_functions.php: -------------------------------------------------------------------------------- 1 | 1, 'bar' => 2]) has a 66% chance of returning bar. 31 | * 32 | * @param array $array 33 | * 34 | * @return mixed 35 | */ 36 | function array_rand_weighted(array $array) 37 | { 38 | $array = array_filter($array, function ($item) { 39 | return $item >= 1; 40 | }); 41 | 42 | if (! count($array)) { 43 | return; 44 | } 45 | $totalWeight = array_sum($array); 46 | 47 | foreach ($array as $value => $weight) { 48 | if (rand(1, $totalWeight) <= $weight) { 49 | return $value; 50 | } 51 | $totalWeight -= $weight; 52 | } 53 | } 54 | 55 | /** 56 | * Determine if all given needles are present in the haystack. 57 | * 58 | * @param array|string $needles 59 | * @param array $haystack 60 | * 61 | * @return bool 62 | */ 63 | function values_in_array($needles, array $haystack) 64 | { 65 | if (! is_array($needles)) { 66 | $needles = [$needles]; 67 | } 68 | 69 | return count(array_intersect($needles, $haystack)) === count($needles); 70 | } 71 | 72 | /** 73 | * Determine if all given needles are present in the haystack as array keys. 74 | * 75 | * @param array|string $needles 76 | * @param array $haystack 77 | * 78 | * @return bool 79 | */ 80 | function array_keys_exist($needles, array $haystack) 81 | { 82 | if (! is_array($needles)) { 83 | return array_key_exists($needles, $haystack); 84 | } 85 | 86 | return values_in_array($needles, array_keys($haystack)); 87 | } 88 | 89 | /** 90 | * Returns an array with two elements. 91 | * 92 | * Iterates over each value in the array passing them to the callback function. 93 | * If the callback function returns true, the current value from array is returned in the first 94 | * element of result array. If not, it is return in the second element of result array. 95 | * 96 | * Array keys are preserved. 97 | * 98 | * @param array $array 99 | * @param callable $callback 100 | * 101 | * @return array 102 | */ 103 | function array_split_filter(array $array, callable $callback) 104 | { 105 | $passesFilter = array_filter($array, $callback); 106 | 107 | $negatedCallback = static function ($item) use ($callback) { 108 | return ! $callback($item); 109 | }; 110 | 111 | $doesNotPassFilter = array_filter($array, $negatedCallback); 112 | 113 | return [$passesFilter, $doesNotPassFilter]; 114 | } 115 | 116 | /** 117 | * Split an array in the given amount of pieces. 118 | * 119 | * @param array $array 120 | * @param int $numberOfPieces 121 | * @param bool $preserveKeys 122 | * @throws \InvalidArgumentException if the provided argument $numberOfPieces is lower than 1 123 | * 124 | * @return array 125 | */ 126 | function array_split(array $array, $numberOfPieces = 2, $preserveKeys = false) 127 | { 128 | if ($numberOfPieces <= 0) { 129 | throw new \InvalidArgumentException('Number of pieces parameter expected to be greater than 0'); 130 | } 131 | 132 | if (count($array) === 0) { 133 | return []; 134 | } 135 | 136 | $splitSize = ceil(count($array) / $numberOfPieces); 137 | 138 | return array_chunk($array, $splitSize, $preserveKeys); 139 | } 140 | 141 | /** 142 | * Returns an array with the unique values from all the given arrays. 143 | * 144 | * @param \array[] $arrays 145 | * 146 | * @return array 147 | */ 148 | function array_merge_values(array ...$arrays) 149 | { 150 | $allValues = array_reduce($arrays, static function ($carry, $array) { 151 | return array_merge($carry, $array); 152 | }, []); 153 | 154 | return array_values(array_unique($allValues)); 155 | } 156 | 157 | /** 158 | * Flatten an array of arrays. The `$levels` parameter specifies how deep you want to 159 | * recurse in the array. If `$levels` is -1, the function will recurse infinitely. 160 | * 161 | * @param array $array 162 | * @param int $levels 163 | * 164 | * @return array 165 | */ 166 | function array_flatten(array $array, $levels = -1) 167 | { 168 | if ($levels === 0) { 169 | return $array; 170 | } 171 | 172 | $flattened = []; 173 | 174 | if ($levels !== -1) { 175 | --$levels; 176 | } 177 | 178 | foreach ($array as $element) { 179 | $flattened[] = is_array($element) ? array_flatten($element, $levels) : [$element]; 180 | } 181 | 182 | return array_merge([], ...$flattened); 183 | } 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Some handy array functions 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/array-functions.svg?style=flat-square)](https://packagist.org/packages/spatie/array-functions) 4 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 5 | [![Build Status](https://img.shields.io/travis/spatie/array-functions/master.svg?style=flat-square)](https://travis-ci.org/spatie/array-functions) 6 | [![Quality Score](https://img.shields.io/scrutinizer/g/spatie/array-functions.svg?style=flat-square)](https://scrutinizer-ci.com/g/spatie/array-functions) 7 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/860364d5-1d74-4cf8-bdb1-c5e18cdc8a70/mini.png)](https://insight.sensiolabs.com/projects/860364d5-1d74-4cf8-bdb1-c5e18cdc8a70) 8 | [![Total Downloads](https://img.shields.io/packagist/dt/spatie/array-functions.svg?style=flat-square)](https://packagist.org/packages/spatie/array-functions) 9 | 10 | This package provides some handy array functions. 11 | 12 | Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). 13 | 14 | ## Support us 15 | 16 | [](https://spatie.be/github-ad-click/array-functions) 17 | 18 | We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). 19 | 20 | We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). 21 | 22 | ## Postcardware 23 | 24 | You're free to use this package (it's [MIT-licensed](LICENSE.md)), but if it makes it to your production environment you are required to send us a postcard from your hometown, mentioning which of our package(s) you are using. 25 | 26 | Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium. 27 | 28 | The best postcards will get published on the open source page on our website. 29 | 30 | ## Install 31 | 32 | You can install this package via composer: 33 | 34 | ``` bash 35 | composer require spatie/array-functions 36 | ``` 37 | 38 | ## Usage 39 | 40 | The following functions are provided in the `Spatie`-namespace: 41 | 42 | ### array_rand_value 43 | ```php 44 | /** 45 | * Get a random value from an array. 46 | * 47 | * @param array $array 48 | * @param int $numReq The amount of values to return 49 | * @return mixed 50 | */ 51 | function array_rand_value(array $array, $numReq = 1) 52 | ``` 53 | 54 | ### array_rand_weighted 55 | ```php 56 | /** 57 | * Get a random value from an array, with the ability to skew the results. 58 | * Example: array_rand_weighted(['foo' => 1, 'bar' => 2]) has a 66% chance of returning bar. 59 | * 60 | * @param array $key 61 | * 62 | * @return mixed 63 | */ 64 | function array_rand_weighted(array $array) 65 | ``` 66 | 67 | ### values_in_array 68 | ```php 69 | /** 70 | * Determine if all given needles are present in the haystack. 71 | * 72 | * @param array|string $needles 73 | * @param array $haystack 74 | * 75 | * @return bool 76 | */ 77 | function values_in_array($needles, array $haystack) 78 | ``` 79 | 80 | ### array_keys_exist 81 | ```php 82 | /** 83 | * Determine if all given needles are present in the haystack as array keys. 84 | * 85 | * @param array|string $needles 86 | * @param array $haystack 87 | * 88 | * @return bool 89 | */ 90 | function array_keys_exist($needles, array $haystack) 91 | ``` 92 | 93 | ### array_split_filter 94 | ```php 95 | /** 96 | * Returns an array with two elements. 97 | * 98 | * Iterates over each value in the array passing them to the callback function. 99 | * If the callback function returns true, the current value from array is returned in the first 100 | * element of result array. If not, it is return in the second element of result array. 101 | * 102 | * Array keys are preserved. 103 | * 104 | * @param array $array 105 | * @param callable $callback 106 | * @return array 107 | * 108 | */ 109 | function array_split_filter(array $array, callable $callback) 110 | ``` 111 | 112 | ### array_split 113 | ```php 114 | /** 115 | * Split an array in the given amount of pieces. 116 | * 117 | * @param array $array 118 | * @param int $numberOfPieces 119 | * @param bool $preserveKeys 120 | * @throws \InvalidArgumentException 121 | * @return array 122 | */ 123 | function array_split(array $array, $numberOfPieces = 2, $preserveKeys = false) 124 | ``` 125 | 126 | ### array_merge_values 127 | ```php 128 | /** 129 | * Returns an array with the unique values from all the given arrays 130 | * 131 | * @param \array[] $arrays 132 | * @return array 133 | */ 134 | function array_merge_values(array ... $arrays) 135 | ``` 136 | 137 | ### array_flatten 138 | ```php 139 | /** 140 | * Flatten an array of arrays. The `$levels` parameter specifies how deep you want to 141 | * recurse in the array. If `$levels` is -1, the function will recurse infinitely. 142 | * 143 | * @param array $array 144 | * @param int $levels 145 | * 146 | * @return array 147 | */ 148 | function array_flatten(array $array, $levels = -1) 149 | ``` 150 | 151 | ## Change log 152 | 153 | Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. 154 | 155 | ## Testing 156 | 157 | You can run the tests with: 158 | 159 | ```bash 160 | vendor/bin/phpunit 161 | ``` 162 | 163 | ## Contributing 164 | 165 | Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. 166 | 167 | ## Security 168 | 169 | If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker. 170 | 171 | ## Credits 172 | 173 | - [Freek Van der Herten](https://github.com/freekmurze) 174 | - [All Contributors](../../contributors) 175 | 176 | ## About Spatie 177 | Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). 178 | 179 | ## License 180 | 181 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 182 | --------------------------------------------------------------------------------