Create a list of devices and interfaces
    - set_fact:
        dev_ifc: "{{ dev_ifc|d([]) + [{'dev': item.1, 'ifc': item.0.key}] }}"
      with_subelements:
        - "{{ device_vlans|dict2items }}"
        - value.interfaces
gives
  dev_ifc:
    - {dev: GigabitEthernet1/1, ifc: '1'}
    - {dev: GigabitEthernet1/2, ifc: '1'}
    - {dev: GigabitEthernet1/3, ifc: '1'}
    - {dev: GigabitEthernet1/2, ifc: '20'}
    - {dev: GigabitEthernet1/3, ifc: '30'}
Then, group the list by the devices and create the dictionary
    - set_fact:
        device_vlans: "{{ dict(key|zip(val)) }}"
      vars:
        arr: "{{ dev_ifc|groupby('dev') }}"
        key: "{{ arr|map('first')|list }}"
        val: "{{ arr|map('last')|
                     map('json_query', '[].ifc')|
                     map('community.general.dict_kv', 'interfaces')|
                     list }}"
gives
  device_vlans:
    GigabitEthernet1/1:
      interfaces: ['1']
    GigabitEthernet1/2:
      interfaces: ['1', '20']
    GigabitEthernet1/3:
      interfaces: ['1', '30']
It's possible to avoid iteration in a task. Instead, put the iteration into Jinja2. For example, put the declarations below as appropriate
    dev_ifc_str: |-
      {% for ifc in device_vlans.keys() %}
      {% for dev in device_vlans[ifc]['interfaces'] %}
      - {dev: {{ dev }}, ifc: {{ ifc }}}
      {% endfor %}
      {% endfor %}
    dev_ifc: "{{ dev_ifc_str|from_yaml }}"
    device_vlans2: "{{ dict(_key|zip(_val)) }}"
    _arr: "{{ dev_ifc|groupby('dev') }}"
    _key: "{{ _arr|map('first')|list }}"
    _val: "{{ _arr|map('last')|
                   map('json_query', '[].ifc')|
                   map('community.general.dict_kv', 'interfaces')|
                   list }}"