Prefixing prices of certain product categories with text in Woocommerce
You could reduce your script to this: (untested)
add_filter('woocommerce_get_price_html', 'change_product_price_html');
function change_product_price_html($product, $price) {
    $categories = [&quot;17&quot;];
    if (!is_shop() || !array_intersect_key(array_flip($product-&gt;get_category_ids()), array_flip($categories))) {
        return $price;
    }
    return &quot;&lt;span class=\&quot;woocommerce-Price-amount amount\&quot;&gt;Starting at &lt;/span&gt;{$price}&quot;;
}


pass the $product into the custom function's scope as an argument to avoid the global declaration.

merge the un-prefixed return conditions into a single expression.

while only a benchmark executed on your system will tell the real truth, I am employing a key-based comparison between two arrays.  The downside is that it may do more work than it needs to (by finding multiple matches). The good news is, it is not going to perform multiple full array scans like a looped in_array() technique might.  I'm not going to be too pushy about how to best compare the two category arrays -- I just wanted to show an alternative.


Alternatively, this will be an easier array-to-array comparison to read:
if (!is_shop() || !array_intersect($product-&gt;get_category_ids(), $categories)) {
    return $price;
}

I assume you were calling your posted function like change_product_price_html($price);.
To add the $product variable as the first expected argument, call my custom function like this:
change_product_price_html($product, $price);