If I start with a yaml object provided by test-kitchen like this;

vars:
  wp_sites:
    - site_subdomain: wordpress1
      theme: twentyseventeen
      site_tld: testbox
    - { site_subdomain: wordpress2, theme: just-pink, site_tld: testbox }
    - site_subdomain: wordpress3
      plugins:
        - disable-comments
      site_tld: testbox

I might need to process the subkeys of that in some way. But unfortunately the set_fact module is pretty simple, and expects to receive a single variable as output. You can’t for example do this;

- set_fact:
    wp_sites[{ { item }}]:
      plugins: "{{ wp_site.plugins|default([]) }}"
   with_items: "{{ wp_sites }}"

as the subkey cannot be complex. So you have to take advantage of jinjas methods for aggregating

- set_fact:
    wp_sites[{ { item }}]:
      plugins: "{{ wp_site.plugins|default([]) }}"
      theme: "{{ wp_site.theme|default('') }}"
      site: "{{ wp_site.site_subdomain }}.{{ wp_site.site_domain | default(ansible_hostname) }}.{{ wp_site.site_tld }}"
      site_subdomain: "{{ wp_site.site_tld|default('') }}"
      site_domain: "{{ wp_site.site_tld|default('') }}"
      site_tld: "{{ wp_site.site_tld|default('') }}"
   with_items: "{{ wp_sites }}"

The new combine filter makes it possible to build up hashes using set_fact. Note the use of default({}) to address the possibility that x is not defined.

# x → {'a': 111, 'b': 222, 'c': 333}
- set_fact:
    x: "{{ x|default({})|combine({item.0: item.1}) }}"
  with_together:
    - ['a', 'b', 'c']
    - [111, 222, 333]

Thanks to the union filter, you can do the same with lists. Combining these techniques makes it possible to build up complex data structures dynamically.

# y → [{'a':123}, {'b':456}, {'c':789}]
- set_fact:
    y: "{{ y|default([])|union([{item.0: item.1}]) }}"
  with_together:
    - ['a', 'b', 'c']
    - [111, 222, 333]