Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django template - How do i iterate two dictionary at same time

Tags:

django

I am new to Django. How do i iterate over 2 dictionary at same time, example:

test1 = {'x':20,'y':10}  test2 = {'x':15,'y':5}  

since they have same key i have tried like

 {% for k,v in test.iteritems %}
    <td >{{ k }} <td>
    <td >{{ v }} <td>
    <td >{{ test2[k] }} <td>
 {% endfor %}

test2[k] giving me error. I am looking for any other way to access test2's values inside test1 loop.

like image 460
user1708597 Avatar asked May 06 '13 18:05

user1708597


1 Answers

Combine your dictionaries into a list container:

tests = [test1, test2]

...in which case, you can easily iterate in the template like so:

{% for test in tests %}
    <tr>
        <td> {{ test.x }} </td>
        <td> {{ test.y }} </td>
    </tr>
{% endfor %}

Should you want them in the same loop/row in the template, you can make a list container of tuples, e.g.:

tests = [(test1, test2), ]

...

{% for test_tuple in tests %}
    <tr>
        <td> {{ test_tuple.0.x }} </td>
        <td> {{ test_tuple.0.y }} </td>
        <td> {{ test_tuple.1.x }} </td>
        <td> {{ test_tuple.1.y }} </td>
    </tr>
{% endfor %}

Edit per comment requesting key name in template

With one test per table row:

{% for test in tests %}
    <tr>
    {% for key, value in test.items %}
        <td> {{ key }} = {{ value }} </td>
    {% endfor %}
    </tr>
{% endfor %}

or with multiple tests per table row:

{% for test_tuple in tests %}
    <tr>
    {% for test in test_tuple %}
        {% for key, value in test.items %}
            <td> {{ key }} = {{ value }} </td>
        {% endfor %}
    {% endfor %}
    </tr>
{% endfor %}

The above may be ambiguous if the tests have the same key(e.g. x=2, y=3, x=4, y=2, x=3, y=5)... an alternative with the index printed as a subscript:

{% for test_tuple in tests %}
    <tr>
    {% for in test_tuple.count %}
        {% for key, value in test.items %}
            <td> {{ key }}<sub>{{ forloop.parentloop.counter }}</sub> = {{ value }} </td>
        {% endfor %}
    {% endfor %}
    </tr>
{% endfor %}

This would print x1, y1, x2, y2, etc.


Edit again RE: display multiple x values, y values inline/in same cell or row

In this case, I would manipulate the data structures BEFORE sending data to the template.

I would create a list of x values and a list of y values:

tests = [test1, test2]
x_values = map(lambda test: test['x'], tests)
y_values = map(lambda test: test['y'], tests)

...and then make sure you send x_values and y_values to the template.

If you want it to be dynamically, you could try to introspect what the parameters are in the test dictionaries (e.g. 'x' or 'y' or something unknown before run-time)...

tests = [test1, test2, test3]
parameters = reduce(lambda accumulator, test: accumulator |= set(test.keys()), tests, set())

This code sets the initial value of parameters AKA accumulator equal to set() then uses the union operator |= to append all keys in any test object to the set... the end result is that you have a set looking like set(['x', 'y']) where the parameter is only counted once. Dynamic introspection of parameters is tricky, so you may want to stick to the simpler x_values and y_values above if you know you are working with only two variables.

Next, you create a list of values for each parameter:

# create a dictionary with keys X, Y and values list(x1,x2,x3), list(y1,y2,y3)
values_dictionary = dict()
# iterate through parameters X, Y, Z, ...
for parameter in parameters:
    # retrieve the parameter value IF IT EXISTS or else append None to new list
    values_for_parameter = map(lambda test: test.get(parameter, None), tests)
    # remove the None values from the resultant list
    values_dictionary[parameter] = filter(lambda value: value is not None, values_for_parameter)

# sample result: values_dictionary['x'] = [1, 5, 8, 4, 2, 3]

Now you have much more useful data structures for rendering in the template. For example:

{% for parameter, values in values_dictionary.items %}
    <tr>
        <td> {{ parameter }} </td>
        <td>
            {% for value in values %}
                {{ value }}
                {% if not forloop.lastloop %}, {% endif %}
            {% endfor %}
        </td>
    </tr>
{% endfor %}
like image 100
pztrick Avatar answered Sep 29 '22 00:09

pztrick