Check if character string is a valid color representation
Your first idea (using col2rgb()
to test color names' validity for you) seems good to me, and just needs to be vectorized. As for whether it seems pretty or not ... lots/most R functions aren't particularly pretty "under the hood", which is a major reason to create a function in the first place! Hides all those ugly internals from the user.
Once you've defined areColors()
below, using it is easy as can be:
areColors <- function(x) {
sapply(x, function(X) {
tryCatch(is.matrix(col2rgb(X)),
error = function(e) FALSE)
})
}
areColors(c(NA, "black", "blackk", "1", "#00", "#000000"))
# <NA> black blackk 1 #00 #000000
# TRUE TRUE FALSE TRUE FALSE TRUE
How to check if a string is a valid hex color representation?
/^#[0-9A-F]{6}$/i.test('#AABBCC')
To elaborate:
^ ->
match beginning# ->
a hash[0-9A-F] ->
any integer from 0 to 9 and any letter from A to F{6} ->
the previous group appears exactly 6 times$ ->
match endi ->
ignore case
If you need support for 3-character HEX codes, use the following:
/^#([0-9A-F]{3}){1,2}$/i.test('#ABC')
The only difference here is that
[0-9A-F]{6}
is replaced with
([0-9A-F]{3}){1,2}
This means that instead of matching exactly 6 characters, it will match exactly 3 characters, but only 1 or 2 times. Allowing ABC
and AABBCC
, but not ABCD
Combined solution :
var reg=/^#([0-9a-f]{3}){1,2}$/i;
console.log(reg.test('#ABC')); //true
console.log(reg.test('#AABBCC')); //true
Check if a string defines a color
Here is the way to check if the string defines a color using matplotlib:
>>> from matplotlib.colors import is_color_like
>>>
>>> is_color_like('red')
True
>>> is_color_like('re')
False
>>> is_color_like(0.5)
False
>>> is_color_like('0.5')
True
>>> is_color_like(None)
False
>>>
>>> matplotlib.colors.__file__
'/usr/lib/python2.7/site-packages/matplotlib/colors.py'
In the source code of the matplotlib.colors module it's written:
The module also provides functions for checking whether an object can be
interpreted as a color (:func:is_color_like
), for converting such an object
to an RGBA tuple (:func:to_rgba
) or to an HTML-like hex string in the
#rrggbb
format (:func:to_hex
), and a sequence of colors to an(n, 4)
RGBA array (:func:to_rgba_array
). Caching is used for efficiency.
How to identify a given string is hex color format
Note: This is strictly for validation, i.e. accepting a valid hex color. For actual parsing you won't get the individual parts out of this.
^#(?:[0-9a-fA-F]{3}){1,2}$
For ARGB:
^#(?:[0-9a-fA-F]{3,4}){1,2}$
Dissection:
^ anchor for start of string
# the literal #
( start of group
?: indicate a non-capturing group that doesn't generate backreferences
[0-9a-fA-F] hexadecimal digit
{3} three times
) end of group
{1,2} repeat either once or twice
$ anchor for end of string
This will match an arbitrary hexadecimal color value that can be used in CSS, such as #91bf4a
or #f13
.
How to check if a string is an rgb hex string
Normally, the best way to see if a string matches some simple format is to actually try to parse it. (Especially if you're only checking so you can then parse it if valid, or print an error if not.) So, let's do that.
The standard library is full of all kinds of useful things, so it's always worth searching. If you want to parse a hex string, the first thing that comes up is binascii.unhexlify
. We want to unhexlify everything after the first #
character. So:
import binascii
def parse_bgcolor(bgcolor):
if not bgcolor.startswith('#'):
raise ValueError('A bgcolor must start with a "#"')
return binascii.unhexlify(bgcolor[1:])
def is_bgcolor(bgcolor):
try:
parse_bgcolor(bgcolor)
except Exception as e:
return False
else:
return True
This accepts 3-character hex strings (but then so do most data formats that use #
-prefixed hex RGB), and even 16-character ones. If you want to add a check for the length, you can add that. Is the rule == 6
or in (3, 6)
or % 3 == 0
? I don't know, but presumably you do if you have a rule you want to add.
If you start using parse_bgcolor
, you'll discover that it's giving you a bytes
with 6 values from 0-255, when you really wanted 3 values from 0-65535. You can combine them manually, or you can parse each two-character pair as a number (e.g., with int(pair, 16)
), or you can feed the 6-char bytes
you already have into, say, struct.unpack('>HHH')
. Whatever you need to do is pretty easy once you know exactly what you want to do.
Finally, if you're trying to parse CSS or HTML, things like red
or rgb(1, 2, 3)
are also valid colors. Do you need to handle those? If so, you'll need something a bit smarter than this. The first thing to do is look at the spec for what you're trying to parse, and work out the rules you need to turn into code. Then you can write the code.
Validating if a string is a valid ARGB
For either language, you can use regular expressions to ensure a string matches your expectations. Here are some examples in Typescript and C#.
Typescript
const argbRegex = /^#[0-9a-fA-F]{8}$/;
argbRegex.test("#ffffffff"); // true
argbRegex.test("#gggggggg"); // false
C#
Regex argbRegex = new Regex("^#[0-9a-fA-F]{8}$");
argbRegex.IsMatch("#ffffffff"); // True
argbRegex.IsMatch("#gggggggg"); // False
Since you didn't mention it in your question, there are some things that you might want to consider that I did not cover:
- Should a 3 character RGB string be a valid ARGB string?
- Should a 6 character RGB string be a valid ARGB string?
- Do you strictly require the # symbol?
- Do you need to extract the decimal values for each ARGB component?
However, if all you need to do is validate the string is strictly in the 8 characters ARGB format, the above examples will work ok.
Check if string is valid representation of hex number
I would have thought that it's quickest to attempt to convert your string to an integral type and deal with any exception. Use code like this:
int num = Int32.Parse(s, System.Globalization.NumberStyles.HexNumber);
The resulting code is possibly easier to follow than a regular expression and is particularly useful if you need the parsed value (else you could use Int32.TryParse
which is adequately documented in other answers).
(One of my favourite quotations is by Jamie Zawinski: "Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems.")
Related Topics
Ggplot Object Not Found Error When Adding Layer with Different Data
Observeevent Shiny Function Used in a Module Does Not Work
Xpath to Extract Text After Br Tags in R
Saving a List of Plots by Their Names()
Get Stack Trace on Trycatch'Ed Error in R
Joining Two Datasets Using Fuzzy Logic
R Lubridate Converting Seconds to Date
Easiest Way to Discretize Continuous Scales for Ggplot2 Color Scales
Extracting Coefficients and Their Standard Error for Each Unit in an Lme Model Fit
Linear Models in R with Different Combinations of Variables
What Are the Caveats of Using Source Versus Parse & Eval
Ggplot2:How to Reduce the Width and the Space Between Bars with Geom_Bar
Multiple Colors in a Facet Strip Background
What Are Productive Ways to Debug Rcpp Compiled Code Loaded in R (On Os X Mavericks)
How to Make Variable Available to Namespace at Loading Time