JSONB Data Type Modification in Postgresql

The key insight is that with jsonb_each and jsonb_object_agg you can round-trip a JSON object in a subquery:

SELECT id, (
  SELECT jsonb_object_agg(key, value)
  FROM jsonb_each(cards)
) AS result
FROM test;

(online demo)

Now you can JOIN these key-value pairs against the jsonb_array_elements of your array input. Your colleague was close, but not quite right: it requires a full outer join, not just a left (or right) join to get all the desired object keys for your output, unless one of your inputs is a subset of the other.

SELECT id, (
  SELECT jsonb_object_agg(COALESCE(obj_key, arr_value), …)
  FROM jsonb_array_elements_text('["1", "2", "3"]') AS arr(arr_value)
  FULL OUTER JOIN jsonb_each(cards) AS obj(obj_key, obj_value) ON obj_key = arr_value
) AS result
FROM test;

(online demo)

Now what's left is only the actual calculation and the conversion to an UPDATE statement:

UPDATE test
SET cards = (
  SELECT jsonb_object_agg(
    COALESCE(key, arr_value),
    COALESCE(obj_value::int, 0) + (arr_value IS NOT NULL)::int
  )
  FROM jsonb_array_elements_text('["1", "2", "3"]') AS arr(arr_value)
  FULL OUTER JOIN jsonb_each_text(cards) AS obj(key, obj_value) ON key = arr_value
);

(online demo)