33

How to remove duplicated items in array on Twig?

I have array value in twig such as.

{{ set array = ["testA","testB","testA","testC","testB"] }}

I want to remove duplicated items and use only testA,testB,testC

{% for name in array%}
 //skip the duplicate items and use only testA,testB,testC
{% endfor %}

How can I make it ?

COil
7,6763 gold badges54 silver badges112 bronze badges
asked Jul 22, 2013 at 13:06

7 Answers 7

64

Twig is a VIEW engine, and should not be used - in theory - to manipulate data. It's a (very) good practice to use (assumingly) PHP to gather data, do all necessary manipulations and then pass the right data to your view.

That said, here's how you can do it in pure Twig syntax:

{% set newArray = [] %}
{% for name in array %}
 {% if name not in newArray %}
 My name is {{name}}
 {% set newArray = newArray|merge([name]) %}
 {% endif %}
{% endfor %}
answered Jul 22, 2013 at 19:46
Sign up to request clarification or add additional context in comments.

2 Comments

Classic MVC strictness question, when is a data manipulation operation inappropriate for inclusion in a view? For example, is it inappropriate to change a word to uppercase? There does not appear to be an unambiguous guiding rule or principle. Not that I have seen.
Sometimes it's hard to decide where you draw the line... Twig being an extremely powerful view engine doesn't make that decision easier. I would definately consider changing text to uppercase to be a responsibility of the view layer. Or using CSS would even be better (assuming you're generating html)
16

In this case, as @Webberig said it's better to prepare your data before the rendering of the view. But when you have a more complex process and if is related to the view you can create a Twig Extension, with an extension the code would look like:

MyTwigExtension.php for Twig versions 1.12 and greater:

/**
 * {@inheritdoc}
 */
public function getFunctions()
{
 return array(
 new \Twig_SimpleFunction('array_unset', array($this, 'arrayUnset'))
 );
}

If you are on a Twig version earlier than 1.12, use this MyTwigExtension.php instead:

/**
 * {@inheritdoc}
 */
public function getFunctions()
{
 return array(
 'array_unset' => new \Twig_Function_Method($this, 'arrayUnset')
 );
}
/**
 * Delete a key of an array
 *
 * @param array $array Source array
 * @param string $key The key to remove
 *
 * @return array
 */
public function arrayUnset($array, $key)
{
 unset($array[$key]);
 return $array;
}

Twig:

{% set query = array_unset(query, 'array_key') %}
answered Oct 24, 2014 at 7:42

Comments

15

You can do it in one line since Twig 1.41 and 2.10:

{% set unique = array|reduce(
 (unique, item) => item in unique ? unique : unique|merge([item]), []
) %}

In your example:

{% for name in array|reduce((unique, item) => item in unique ? unique : unique|merge([item]), []) %}
 My name is {{name}}
{% endfor %}
7ochem
2,3661 gold badge37 silver badges45 bronze badges
answered Jul 21, 2019 at 11:53

Comments

4

Quick Answer (TL;DR)

  • A custom Twig filter array_unique permits removal of duplicates
  • This can be directly carried over from native PHP

Detailed Answer

Context

  • Twig 2.x (latest version as of Wed 2017年02月08日)
  • Alternate approach in comparison to other approaches specified elsewhere

Problem

  • Scenario:
  • DeloperSutasSugas wishes to dedupe an array
  • PHP built-in array_unique function can do the job

Example01

  • DeloperSutasSugas starts with a sequentially-indexed array
  • transform from BEFORE into AFTER
{%- set mylist = ['alpha','alpha','bravo','charlie','alpha','alpha','delta','echo'] -%}
BEFORE: 
['alpha','alpha','bravo','charlie','alpha','alpha','delta','echo']
AFTER: 
['alpha','bravo','charlie','delta','echo']

Solution

Custom filter
[...]
// {"define_filter_":"array_unique" ,"desc":"PHP array_unique function" },
$filter = new Twig_SimpleFilter('array_unique', function ( $vinp=Array() ) {
 $vout = ( $vinp );
 $vout = array_unique( $vout );
 $vout = array_values( $vout ); // PHP annoyance array reindex -- optional
 return $vout;
});
$twig->addFilter($filter);
//;;
[...]
Output
{%- set mylist = mylist|array_unique -%} 

Pitfalls

  • Requires addon filter (the solution does not work with native Twig)

See also

answered Feb 8, 2017 at 20:19

Comments

2

For symfony !

Service : app/config/service.yml

twig_array_unique_function:
 class: AppBundle\Twig\ArrayUniqueFunction
 tags:
 - { name: twig.function }

Class : src/AppBundle/Twig/ArrayUniqueFunction.php

<?php
namespace AppBundle\Twig;
class ArrayUniqueFunction extends \Twig_Extension
{
 public function getFilters()
 {
 return [new \Twig_SimpleFilter('array_unique', 'array_unique')];
 }
 public function getFunctions()
 {
 return [new \Twig_SimpleFunction('array_unique', 'array_unique')];
 }
}

Thk : https://github.com/getgrav/grav/blob/develop/system/src/Grav/Common/Twig/TwigExtension.php

answered Mar 16, 2018 at 10:32

Comments

1
{% set keeper = {} %}
{% set throwaway = [] %}
{% for thing in yourSet.all() %}
 {% if thing.id not in throwaway %}
 {% set throwaway = throwaway|merge([thing.id]) %}
 {% set keeper = keeper|merge([{ slug: thing.slug, title: thing.title}]) %}
 {% endif %}
{% endfor %}

Modification on the accepted answer above. I needed to remove duplicates from a set and end up with an object of just slug and title.

answered Apr 13, 2018 at 13:13

Comments

-3

The in operator performs containment test.

It returns true if the left operand is contained in the right.

{% if name in array %}

http://twig.sensiolabs.org/doc/templates.html#containment-operator

answered Jul 22, 2013 at 13:13

2 Comments

How does this answer anything? The OP already knows the in operator.
In the same way that the top answer did ... just not a full example. You can check if the current name is in an array of names you've seen already, if not, add it to the array of seen names; if so, skip it.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.