Using Twig to merge an array and remove duplicates Problem

I'm building a .json file for a search component of a used cars website. The file needs to be built from the output of two sections within CraftCMS, Used Cars and Vans &amp; Trucks. It outputs the "make" of vehicle and it's "models". 

My problem is that there are duplicate "makes"/"models" because they exist in both sections.

Code:

{% set allStock = craft.entries.section(['usedCars','vansTrucks']).level(2) %}
{% for stock in allStock %}
{% set models = stock.getChildren() %}
"{{ stock.make }}" : "{% for stock in models %}{{ stock.model }}{% if not loop.last %}, {% endif %}{% endfor %}"
{% endfor %}


Output:

"Holden" : "Commodore, Ute, Viva"

"Nissan" : "ATLAS, CARAVAN"

"Mazda" : "ATENZA, Axela, CX-7, MAZDA 6, MPV, RX-8, mpv"

"Nissan" : "CARAVAN, DUALIS, FAIRLADY, Liberty, Maxima, NAVARA, NOTE"

Updated

{% set allStock = craft.entries.section(['usedCars','vansTrucks']).level(2) %}
{% set newArray = [] %}
{% for stock in allStock %}
{% set models = stock.getChildren() %}
{% if stock.make not in newArray %}
"{{ stock.make }}" : "{% for stock in models %}{{ stock.model }}{% if not loop.last %}, {% endif %}{% endfor %}"
{% set newArray = newArray|merge([stock.make]) %}
{% endif %}
{% endfor %}


This code will remove the duplicate 'make' and merge but it also removes the models with it. 

Output:

"Holden" : "Commodore, Ute, Viva"

"Mazda" : "ATENZA, Axela, CX-7, MAZDA 6, MPV, RX-8, mpv"

"Nissan" : "CARAVAN, DUALIS, FAIRLADY, Liberty, Maxima, NAVARA, NOTE"

Any help or direction on how to go about merging the models would be greatly appreciated.
You could do it in the twig template

But a template isn't really the best place for something that is this codey, it gets pretty unreadable pretty quick.

Notes:


I start by building arrays of models and afterwards I convert those arrays to the comma seperated strings you require.
It is case-sensitive, you probably have models or makes likes HILUX, hilux, Hilux, these sort of duplicates will not be removed. You can achieve a modicum of case-insensitivity by chucking a few lowers in there.
Instead of hand-writing the json, this uses twig's json_encode filter, tweak the options to suit you.


The template code:

{% set makes = craft.entries.section(['usedCars','vansTrucks']).level(2) %}
{% set data = {} %}

{% for make in makes %}
    {% set make_name = make.make %}

    {# Get the list of models for this make if we have already seen it before, otherwise an empty array #}
    {% if data[make_name] is not defined %}
        {% set data = data|merge({(make_name):[]})%}
    {% endif %}
    {% set make_data = data[make_name] %}

    {# Build an array of model names #}
    {% set models = make.getChildren() %}
    {% for model in models %}
        {% set model_name = model.model %}

        {# Only add this model if we have not seen it before #}
        {% if model_name not in make_data %}
            {% set make_data = make_data|merge([model_name]) %}
        {% endif %}
    {% endfor %}

    {% set data = data|merge({(make_name):make_data}) %}
{% endfor %}

{# Replace the arrays of models we previously built with a comma seperated string of models #}
{% for make_name, models in data %}
    {% set models_string = models|join(",") %}
    {% set data = data|merge({(make_name):models_string}) %}
{% endfor %}

{{ data|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}


Or do it with code

Add your own plugin as per the instructions here: Setting things up

Add a template variable as per the instructions here: Template variables

Your template variable could look like this:

namespace Craft;

class MyAwesomePluginVariable
{
    public function getSearchData()
    {
        // find all makes
        $make_criteria = craft()-&gt;elements-&gt;getCriteria(ElementType::Entry);
        $make_criteria-&gt;level = 2;
        $make_criteria-&gt;section = array('usedCars','vansTrucks');

        $data = array();

        $makes = $make_criteria-&gt;find();
        foreach ($makes as $make) 
        {
            // build array of models for this make
            $model_names = array();
            $models = $make-&gt;getChildren();
            foreach ($models as $model) {
                $model_names[]= $model-&gt;model;
            }

            // combine with previous models for this make and remove duplicates
            if (array_key_exists($make-&gt;make, $data)) {
                $data[$make-&gt;make] = array_unique( array_merge($data[$make-&gt;make], $model_names) );
            } else {
                $data[$make-&gt;make] = array_unique( $model_names );
            }
        }

        // convert model arrays to comma separated strings
        foreach ($data as $make =&gt; $models) {
            $data[$make] = implode(",", $models);
        }

        return $data;
    }

}


And then in your template:

{{ craft.myAwesomePlugin.getSearchData|json_encode(constant('JSON_PRETTY_PRINT'))|raw }}