Skip to content
Advertisement

Trouble converting Javascript source to Python

I’m trying to convert a Javascript function to Python. Most of it was no problem but there’s one statement I’m not sure how to convert:

color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))

The Python so far is:

color = +("0x" + color[:1].replace(
            len(color) < 5 and /./g, '$&$&')
        )

idk what +() or /./g are for. The complete JS function is:

function lightOrDark(color) {
    
    // Variables for red, green, blue values
    var r, g, b, hsp;
    var threshold = 127.5
    // Check the format of the color, HEX or RGB?
    if (color.match(/^rgb/)) {
        
        // If RGB --> store the red, green, blue values in separate variables
        color = color.match(/^rgba?((d+),s*(d+),s*(d+)(?:,s*(d+(?:.d+)?))?)$/);
        
        r = color[1];
        g = color[2];
        b = color[3];
    } else {
        
        // If hex --> Convert it to RGB: http://gist.github.com/983661
        color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
        console.log(color)
        r = color >> 16;
        g = color >> 8 & 255;
        b = color & 255;
    }
    
    // HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
    hsp = Math.sqrt(
        0.299 * (r * r) +
        0.587 * (g * g) +
        0.114 * (b * b)
    )
    
    // Using the HSP value, determine whether the color is light or dark
    return hsp > threshold;
}

Advertisement

Answer

The /./g is a regular expression and the +() coerces a string into a number (and the 0x makes it hexadecimal). In Python you’d use the re module and the int() builtin for that.

The replace duplicates the characters if the color is written in its short form. The Python equivalent is a re.sub(). You use a backslash instead of a dollar for back-references in Python’s regex dialect. So 1 refers to the first matching group.

>>> import re
>>> color = "#123456"
>>> re.sub("(.)", r"11" if len(color)<5 else r"1", color[1:])
'123456'
>>> color = "#abc"
>>> re.sub("(.)", r"11" if len(color)<5 else r"1", color[1:])
'aabbcc'

So for a short string, this replaces each character with itself twice, but for a long string this replaces each character with itself once (no change).

Then you use a base of 16 to convert a hexadecimal string to an int:

>>> int('aabbcc', 16)
11189196

All together:

int(re.sub("(.)", r"11" if len(color)<5 else r"1", color[1:]), 16)
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement