【问题标题】:How to save RGB(A) values in an array?如何将 RGB(A) 值保存在数组中?
【发布时间】:2019-04-07 18:17:07
【问题描述】:

我正在尝试编写一个函数,该函数将采用 RGB(A) 颜色并将其值保存在数组中,并可选择排除 alpha 值。我无法弄清楚如何编写与输入匹配的正则表达式,但我认为我正在寻找这样的东西:

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 );

但它感觉很老套,我找不到选择包含/排除 alpha 的好方法。

感谢您的帮助,如果有与 preg_match 完全不同的方法会更好,我会全力以赴。

【问题讨论】:

  • 为什么不简单地用逗号分割,那么你将有一个包含每个的数组。
  • 我目前正在使用explode() 执行此操作,正如我在最后展示的那样,但是如果我保留它,那么我需要一种方法来从数组中排除不需要的 alpha 值或传递颜色不包括它。

标签: php arrays regex rgb rgba


【解决方案1】:

我的回答不仅会提取您想要的子字符串值,还会执行相当高水平的验证(不是 100% 完美验证)。我将模式从https://stackoverflow.com/a/31245990/2943403 修改为更准确地解决这个问题。我相信您会发现这个答案准确、优雅、直接。

如果您想剥离/简化模式,可以这样做:(Regex101 Demo)
~^rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([.\d]+))?\)$~

代码:(Demo w/ $include_alpha = true) (Demo w/ $include_alpha = false) (Regex101 Demo)

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',
)

附言如果你想使用preg_split(),你可以对你的模式不那么具体。这是给你的单线。 (Demo)

function rgb_array($color, $include_alpha = true) {
    return array_slice(preg_split('~[^\d.]+~', $color, -1, PREG_SPLIT_NO_EMPTY), 0, $include_alpha + 3);
}

【讨论】:

  • 不错!这显然是最完整的答案(对不起,尼克,你的也有效!)我真的不需要验证,但这个函数比我验证的其他方式运行得快得多,所以这仍然很有帮助。
  • @Shoelaced 完全没有问题 - 你应该始终接受 最佳 答案,即使在你接受另一个答案之后确实出现了。
【解决方案2】:

如果你想要一个正则表达式解决方案,这里是:

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

它在开始时匹配 'rgb',然后是可选的 'a' 和左侧的 parenthes,然后它创建 3 个相似的组,匹配可选的白色 Space,后跟一个或多个 digits。第四个组是可选的,将匹配一个或多个digits,可选地后跟一个dot,以及一个或多个digits

颜色将位于索引 1、2、3 和 4(如果可用)。

【讨论】:

  • 这匹配无效的 rgb 事物,例如 rbga(0, 0, 0) 或 rgb(0, 0, 0, 0)。它也只允许在数字周围有一个空格。更广泛的方法是这样的(尽管这会根据类型将事物置于不同的位置参数中,并且还会遗漏许多其他有效的 rgb/rgba 事物并且还接受一堆无效的东西):/(?:(rgb )(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*)|(rgba)(\s*(\d+)\s* ,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+(?:\.\d+)?)\s*))/i 同样,这是'不是一个好的解决方案,所以不要使用它,但它显示了我的意思。
  • 谢谢!这行得通,但我最终使用了preg_split 解决方案。另外为了记录,我正在单独验证输入...
【解决方案3】:

您可以使用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
)

【讨论】:

  • 谢谢!这似乎是最简单的,我最终使用array_pop() 有条件地删除 alpha 值。
【解决方案4】:

稍微改进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 类型转换为 floatint 会从字符串中删除多余字符的事实从字符串中提取数字:

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

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

【讨论】:

  • 第二个看起来很酷,但奇怪的是它最终总是将红色值返回为 0...
  • 没错,我的错。应该有额外的行 $color = trim($color, 'rgba()'); 作为函数的第一行来解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2012-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
  • 1970-01-01
相关资源
最近更新 更多