Ejemplo n.º 1
0
/**
 * Gets an array of slices of size `$size` from an array.
 * ```php
 * $pairs = slices(2);
 * $pairs([1, 2, 3, 4, 5]); // [[1, 2], [3, 4], [5]]
 * $pairs("Hello World"); // ['He', 'll', 'o ', 'Wo', 'rl', 'd']
 * slices(5, [1, 2]); // [[1, 2]]
 * slices(3, []) // []
 * slices(3, '') // ''
 * ```
 *
 * @signature Number -> [a] -> [[a]]
 * @signature Number -> String -> [String]
 * @param  int $size
 * @param  array $list
 * @return array
 */
function slices()
{
    $slices = function ($size, $list) {
        if (empty($list)) {
            return is_string($list) ? '' : [];
        }
        if (length($list) <= $size) {
            return [$list];
        }
        return prepend(take($size, $list), slices($size, remove($size, $list)));
    };
    return apply(curry($slices), func_get_args());
}
Ejemplo n.º 2
0
/**
 * Splits a string into chunks without spliting any group surrounded with some
 * specified characters. `$surrounders` is a string where each pair of characters
 * specifies the starting and ending characters of a group that should not be split.
 * ```php
 * $groups = chunks('(){}', ',');
 * $groups('1,2,(3,4,5),{6,(7,8)},9'); // ['1', '2', '(3,4,5)', '{6,(7,8)}', '9']
 *
 * $names = chunks('()""', ' ');
 * $names('Foo "Bar Baz" (Some other name)'); // ['Foo', 'Bar Baz', 'Some other name']
 * ```
 *
 * @signature String -> String -> String -> [String]
 * @param  string $surrounders
 * @param  string $separator
 * @param  sring $text
 * @return array
 */
function chunks()
{
    $chunks = function ($surrounders, $separator, $text) {
        // Let's assume some values to understand how this function works
        // surrounders = '""{}()'
        // separator = ' '
        // $text = 'foo ("bar baz" alpha) beta'
        $surrounders = map(slices(1), slices(2, $surrounders));
        // [['"'. '"'], ['{'. '}'], ['(', ')']]
        $openings = map(get(0), $surrounders);
        // ['"', '{', '(']
        $closings = map(get(1), $surrounders);
        // ['"', '}', ')']
        $numOfSurrounders = length($surrounders);
        // 3
        $indexes = keys($surrounders);
        // [0, 1, 2]
        $items = split($separator, $text);
        // ['foo', '("bar', 'baz"', 'alpha)', 'beta']
        // The initial state
        $state = (object) ['chunks' => [], 'counts' => array_fill(0, $numOfSurrounders, 0), 'total' => 0];
        // We will iterate over $items and update the $state while adding them
        // For each item we need to update counts and chunks
        // Updates count for a single surrender (the surrender at $index)
        // $item : the item we are adding
        // $counts : the previous counts
        $updateCountAt = curry(function ($item, $counts, $index) use($openings, $closings) {
            $count = occurences(__(), $item);
            return $openings[$index] == $closings[$index] ? ($counts[$index] + $count($openings[$index])) % 2 : $counts[$index] + $count($openings[$index]) - $count($closings[$index]);
        });
        // Updates counts for all surrenders
        $updateCounts = curry(function ($item, $counts) use($indexes, $updateCountAt) {
            return map($updateCountAt($item, $counts), $indexes);
        });
        // Adds an item to the state and returns a new state
        $addItem = function ($state, $item) use($separator, $updateCounts) {
            $counts = $updateCounts($item, get('counts', $state));
            $newChunks = 0 == $state->total ? append($item, $state->chunks) : append(last($state->chunks) . $separator . $item, init($state->chunks));
            return (object) ['chunks' => $newChunks, 'counts' => $counts, 'total' => sum($counts)];
        };
        // Returns the chunks of the resulting state after adding all items
        return get('chunks', reduce($addItem, $state, $items));
    };
    return apply(curry($chunks), func_get_args());
}