<p>You can do this using the <a href="http://twig.sensiolabs.org/doc/functions/attribute.html">twig attribute function</a>:</p>

<pre><code>{% set data = [
    {'column':'1','title':'Quick Facts'}, 
    {'column':'2','title':'Inspiration'}, 
    {'column':'1','title':'Agencies'}, 
    {'column':'2','title':'Industry Experience'}
] %}

{% set cols = {} %}
{% for item in data %}

    {# create a dynamic property if one doesn't exist #}
    {% if not attribute(cols, 'col' ~ item.column) is defined %}
        {% set cols = cols|merge({ ('col' ~ item.column) : [item.title] }) %}

    {# else update the dynamic property with the new title #}
    {% else %}
        {% set titles = attribute(cols, 'col' ~ item.column) %}
        {% set titles = titles|merge([item.title]) %}
        {% set cols = cols|merge({ ('col' ~ item.column) : titles }) %}

    {% endif %}
{% endfor %}

{{ dump(cols) }}

{#
array(2) { 
    ["col1"]=&gt; array(2) {
         [0]=&gt; string(11) "Quick Facts" 
         [1]=&gt; string(8) "Agencies" 
    } 
    ["col2"]=&gt; array(2) { 
        [0]=&gt; string(11) "Inspiration" 
        [1]=&gt; string(19) "Industry Experience" 
    } 
} 
#}
</code></pre>

CC BY-SA 3.0
2014-10-26T23:52:45.910Z
Please note that the column is the same for some blocks, so that there might be two things in column 1.
Ryan
CC BY-SA 3.0
2014-10-27T00:07:30.223Z
It never gets to the second part of the loop. Here it is with "col" http://i.imgur.com/zZg4AKK.png and here it is without http://i.imgur.com/1TKTHj1.png.
Ryan
CC BY-SA 3.0
2014-10-27T02:44:09.213Z
I see it but something is up with Twig - it just doesn't act predictably with arrays in my opinion.I changed to 'cols' but it still only shows up with 3 so it's overwriting the existing column as col1 already exists.
Ryan
CC BY-SA 3.0
2014-10-27T04:39:59.780Z
I actually created a sample data set to work with to test, and discovered the problem. In the old script 'titles' just copied the value rather then being a permanent reference to the 'cols[col1]' object property. If you set the object property again to 'titles' it will set the new titles array properly (overwriting it on each pass with the updated titles array).
Douglas McDonald
CC BY-SA 3.0
2014-10-27T05:33:36.697Z
Nice! I can see it now. Works a treat, thanks Douglas. One thing to note is that if you remove `'col' ~ ` it will no longer work.
Ryan
CC BY-SA 3.0
2014-10-27T05:50:40.267Z
Great! Glad it's working finally (that hurt my brain). I learned through all this that the hash key issue is with php, not with twig. In php, if a hash key is defined as a number it will get redefined as an index [0,1,2,...].
Douglas McDonald
CC BY-SA 3.0
2014-10-26T18:10:03.230Z
2014-10-27T04:54:08.943Z
2014-10-27T04:54:08.943Z
Douglas McDonald
<p>I have content which needs to go into a certain column so I have a field called 'column' there. I can create the array I want by hand:</p>

<pre><code>{%
    set items = {
        1 : {
            0 : 'Quick Facts',
            1 : 'Agencies'
        },
        2 : {
            0 : 'Inspiration',
            1 : 'Industry Experience'
        }
    }
%}
</code></pre>

<p>Where 1 and 2 are the columns, and 0,1 is just a normal index. In a loop it is different. I have tried the same syntax but of course setting the variable in the loop will set the new variable every time and replace the old one. Using merge like below always gives me new keys. Is there a way to do this as easily as PHP?</p>

<pre><code>{% set blocks = {} %}

{% for tab in tabs %}
    {% for key,block in tab.tabItem %}

        {% if block.type == 'about' %}
            {% set blocks = blocks|merge({ (block.column.value) : block.aboutTitle}) %}
        {% endif %}

    {% endfor %}
{% endfor %}
</code></pre>

<p>This is the output of the two pieces of code (first being what I want). I'd like the <code>block.column.value</code> to be the key.</p>

<p><img src="https://i.sstatic.net/RKEfJm.png" alt="Output"></p>

CC BY-SA 3.0
2014-10-26T14:28:24.707Z
When you `merge` using a hash, my understanding is that it will replace (rather than append) any values that share the same hash key. So it would be impossible to do what your asking using a single loop/set statement. Can you perhaps share the loop that you are using also?
Douglas McDonald
CC BY-SA 3.0
2014-10-26T14:44:57.620Z
Ok, updated with the proper data, and what I have now. You can see it's just a flat array and `block.column.value` isn't being used.
Ryan
CC BY-SA 3.0
2014-10-26T16:50:48.020Z
Don't know if this will help, but I tried to do something similar and found that it interpreted a number as an index instead of a key. Appending a string in front of the number fixed this. i.e. `{% set blocks = blocks|merge({ ('col'~block.column.value) : block.aboutTitle }) %}`
Douglas McDonald
CC BY-SA 3.0
2014-10-26T23:54:08.013Z
Please note that the column is the same for some blocks, so that there might be two things in column 1.
Ryan
<array>
Creating dynamic array and set keys
# Creating dynamic array and set keys

(Asked by: username_0 on 2014-10-26)

I have content which needs to go into a certain column so I have a field called 'column' there. I can create the array I want by hand:
{%
    set items = {
        1 : {
            0 : 'Quick Facts',
            1 : 'Agencies'
        },
        2 : {
            0 : 'Inspiration',
            1 : 'Industry Experience'
        }
    }
%}

Where 1 and 2 are the columns, and 0,1 is just a normal index. In a loop it is different. I have tried the same syntax but of course setting the variable in the loop will set the new variable every time and replace the old one. Using merge like below always gives me new keys. Is there a way to do this as easily as PHP?
{% set blocks = {} %}

{% for tab in tabs %}
    {% for key,block in tab.tabItem %}

        {% if block.type == 'about' %}
            {% set blocks = blocks|merge({ (block.column.value) : block.aboutTitle}) %}
        {% endif %}

    {% endfor %}
{% endfor %}

This is the output of the two pieces of code (first being what I want). I'd like the block.column.value to be the key.

**Tags:** array
> **Comments:**
> **username_1**: When you `merge` using a hash, my understanding is that it will replace (rather than append) any values that share the same hash key. So it would be impossible to do what your asking using a single loop/set statement. Can you perhaps share the loop that you are using also?  
> **username_0**: Ok, updated with the proper data, and what I have now. You can see it's just a flat array and `block.column.value` isn't being used.  
> **username_1**: Don't know if this will help, but I tried to do something similar and found that it interpreted a number as an index instead of a key. Appending a string in front of the number fixed this. i.e. `{% set blocks = blocks|merge({ ('col'~block.column.value) : block.aboutTitle }) %}`  
> **username_0**: Please note that the column is the same for some blocks, so that there might be two things in column 1.  

---

## 1 answers

### Answer by username_1 on 2014-10-26. Score: 19 | Accepted answer

You can do this using the twig attribute function:
{% set data = [
    {'column':'1','title':'Quick Facts'}, 
    {'column':'2','title':'Inspiration'}, 
    {'column':'1','title':'Agencies'}, 
    {'column':'2','title':'Industry Experience'}
] %}

{% set cols = {} %}
{% for item in data %}

    {# create a dynamic property if one doesn't exist #}
    {% if not attribute(cols, 'col' ~ item.column) is defined %}
        {% set cols = cols|merge({ ('col' ~ item.column) : [item.title] }) %}

    {# else update the dynamic property with the new title #}
    {% else %}
        {% set titles = attribute(cols, 'col' ~ item.column) %}
        {% set titles = titles|merge([item.title]) %}
        {% set cols = cols|merge({ ('col' ~ item.column) : titles }) %}

    {% endif %}
{% endfor %}

{{ dump(cols) }}

{#
array(2) { 
    ["col1"]=> array(2) {
         [0]=> string(11) "Quick Facts" 
         [1]=> string(8) "Agencies" 
    } 
    ["col2"]=> array(2) { 
        [0]=> string(11) "Inspiration" 
        [1]=> string(19) "Industry Experience" 
    } 
} 
#}

> **Comments:**
> **username_0**: Please note that the column is the same for some blocks, so that there might be two things in column 1.  
> **username_0**: It never gets to the second part of the loop. Here it is with "col" http://i.imgur.com/zZg4AKK.png and here it is without http://i.imgur.com/1TKTHj1.png.  
> **username_0**: I see it but something is up with Twig - it just doesn't act predictably with arrays in my opinion.I changed to 'cols' but it still only shows up with 3 so it's overwriting the existing column as col1 already exists.  
> **username_1**: I actually created a sample data set to work with to test, and discovered the problem. In the old script 'titles' just copied the value rather then being a permanent reference to the 'cols[col1]' object property. If you set the object property again to 'titles' it will set the new titles array properly (overwriting it on each pass with the updated titles array).  
> **username_0**: Nice! I can see it now. Works a treat, thanks Douglas. One thing to note is that if you remove `'col' ~ ` it will no longer work.  
> **username_1**: Great! Glad it's working finally (that hurt my brain). I learned through all this that the hash key issue is with php, not with twig. In php, if a hash key is defined as a number it will get redefined as an index [0,1,2,...].  

---

