Как сохранить значения RGB (A) в массиве? - PullRequest
0 голосов
/ 04 ноября 2018

Я пытаюсь написать функцию, которая будет принимать цвет RGB (A) и сохранять его значения в массиве, с возможностью исключить альфа-значение. У меня проблемы с выяснением, как написать регулярное выражение, которое будет соответствовать входным данным, но я думаю, что что-то вроде этого - то, что я ищу:

function rgb_array( $color, $include_alpha = true ) {

    $pattern = 'what goes here?';

    $color = preg_match( $pattern, $color, $matches);

    if ( $include_alpha == true && ! empty( $matches[4] ) ) {
        $color = array( $matches[1], $matches[2], $matches[3], $matches[4] );
    } else {
        $color = array( $matches[1], $matches[2], $matches[3] );
    }

    return $color;
}

Я бы хотел иметь возможность использовать любую допустимую форму rgb / rgba:

rgb(0,0,0)
rgb(00,00,00)
rgb(0, 0, 0)
rgb(00, 00, 00)
rgba(0,0,0,0.5)
rgba(255, 255, 255, 1)
etc...

И пусть он создаст массив:

[0] => '00', // red
[1] => '00', // green
[2] => '00', // blue
[3] => '1' // alpha only included if available and desired.

На данный момент я могу сделать это через str_replace:

$color  = 'rgb(12, 14, 85)';
$remove = array( 'rgb', 'a', '(', ')', ' ' );
$color  = str_replace( $remove, '', $color );
$color  = explode( ',', $color );

Но это кажется хакерским, и я не могу найти хороший способ по желанию включить / исключить альфа.

Спасибо за вашу помощь, и если есть совершенно другой подход, чем preg_match, это было бы лучше, я весь слух.

Ответы [ 4 ]

0 голосов
/ 04 ноября 2018

Мой ответ не только извлечет значения подстроки, которые вы хотите, но и дополнительно обеспечит достаточно высокий уровень проверки (а не 100% -ную проверку). Я изменил шаблон с https://stackoverflow.com/a/31245990/2943403, чтобы более точно ответить на этот вопрос. Надеюсь, вы найдете этот ответ точным, элегантным и прямым.

Если вы хотите сократить / упростить шаблон, это будет делать: ( Regex101 Demo )
~^rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([.\d]+))?\)$~

Код: ( Демо w / $ include_alpha = true ) ( Демо w / $ include_alpha = false ) ( Regex101 Демо )

function rgb_array($color, $include_alpha = true) {
    $pattern = '~^rgba?\((25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*,\s*(25[0-5]|2[0-4]\d|1\d{2}|\d\d?)\s*(?:,\s*([01]\.?\d*?))?\)$~';

    if (!preg_match($pattern, $color, $matches)) {
        return [];  // disqualified / no match
    }

    return array_slice($matches, 1, $include_alpha ? 4 : 3);
}

$strings = [
    'rgb(0,0,0)',
    'rgb(00,00,00)',
    'rgb(0, 0, 0)',
    'donkey eggs',
    'rgb(00, 00, 00)',
    'rgba(0,0,0,0.5)',
    'rgba(255, 255, 255, 1)'
];

foreach ($strings as $string) {
    echo "Process: $string\n";
    var_export(rgb_array($string));
    echo "\n";
}

Выход:

Process: rgb(0,0,0)
array (
  0 => '0',
  1 => '0',
  2 => '0',
)
Process: rgb(00,00,00)
array (
  0 => '00',
  1 => '00',
  2 => '00',
)
Process: rgb(0, 0, 0)
array (
  0 => '0',
  1 => '0',
  2 => '0',
)
Process: donkey eggs
array (
)
Process: rgb(00, 00, 00)
array (
  0 => '00',
  1 => '00',
  2 => '00',
)
Process: rgba(0,0,0,0.5)
array (
  0 => '0',
  1 => '0',
  2 => '0',
  3 => '0.5',
)
Process: rgba(255, 255, 255, 1)
array (
  0 => '255',
  1 => '255',
  2 => '255',
  3 => '1',
)

p.s. Если вы хотите использовать preg_split(), вы можете быть гораздо менее точным в отношении своего паттерна. Вот вам одна строчка ( Демо )

function rgb_array($color, $include_alpha = true) {
    return array_slice(preg_split('~[^\d.]+~', $color, -1, PREG_SPLIT_NO_EMPTY), 0, $include_alpha + 3);
}
0 голосов
/ 04 ноября 2018

Если вам нужно решение для регулярных выражений, вот оно:

rgba?\((\s?\d+),(\s?\d+),(\s?\d+)(?:,\s?(\d+(?:\.\d+)?))?\)

Это соответствует 'rgb' в начале, затем необязательный 'a' и левый parenthes, затем он создает 3 аналогичные группы, совпадающие с оптинальным белым Space, за которым следует один или несколько digits. Четвертая группа является необязательной и будет соответствовать одному или нескольким digits, за которыми необязательно следует dot и один или несколько digits.

Цвета будут в индексах 1, 2, 3 и 4 (при наличии).

0 голосов
/ 04 ноября 2018

Вы можете использовать preg_split, чтобы разбить строку на составные части. Регулярное выражение разбивает строку на одну из ведущих rgba(, , или конечную ). Флаг PREG_SPLIT_NO_EMPTY используется, чтобы избежать пустых значений в выходном массиве.

$strings = array('rgb(0,0,0)',
'rgb(00,00,00)',
'rgb(0, 0, 0)',
'rgb(00, 00, 00)',
'rgba(0,0,0,0.5)',
'rgba(255, 255, 255, 1)');
foreach ($strings as $string) {
    print_r(preg_split('/rgba?\(\s*|\s*,\s*|\s*\)/', $string, -1, PREG_SPLIT_NO_EMPTY));
}

Выход:

Array
(
    [0] => 0
    [1] => 0
    [2] => 0
)
Array
(
    [0] => 00
    [1] => 00
    [2] => 00
)
Array
(
    [0] => 0
    [1] => 0
    [2] => 0
)
Array
(
    [0] => 00
    [1] => 00
    [2] => 00
)
Array
(
    [0] => 0
    [1] => 0
    [2] => 0
    [3] => 0.5
)
Array
(
    [0] => 255
    [1] => 255
    [2] => 255
    [3] => 1
)
0 голосов
/ 04 ноября 2018

Немного улучшено explode решение:

function rgb_array($color, $include_alpha = true)
{
    $color = trim($color, 'rgba()');       # "rgba(255, 255, 255, 1)" => "255, 255, 255, 1"
    $color = str_replace(' ', '', $color); # "255, 255, 255, 1"       => "255,255,255,1"
    $color = explode(',', $color);         # "255,255,255,1"          => ["255", "255", "255", "1"]
    $color[] = 1;                          # add extra value to be sure that all parsed colors have transparency

    return array_slice($color, 0, 3 + $include_alpha); # length is 3 or 4, depends on $include_alpha value
}

Вы также можете извлечь числа из строки, основываясь на том факте, что встроенный PHP-тип приведен к float, а int удаляет дополнительные символы из строки:

function rgb_array($color, $include_alpha = true)
{
    $array = array_map('floatval', explode(',', $color));
    $array[] = 1;

    return array_slice($array, 0, 3 + $include_alpha);
}
...