<p>If you don't want to build a custom plugin, this would be a good time to use Twig's <a href="https://twig.symfony.com/doc/2.x/filters/reduce.html" rel="nofollow noreferrer">reduce</a> filter, which takes a set of values and iterates over them to output a single value based on supplied logic.</p>
<p>Using Andy's answer as the basis might look like this (untested):</p>
<pre><code>{% set currentYear = now|date('Y') %}

{% set loyaltyScore = currentUser.years.all()|reduce(
    (score, year) =&gt; 
        score == 0 and year == currentYear or 
        score &gt; 0 and year == currentYear - 1 ?
        score + 1,
        0
) %}
</code></pre>
<p>I'm assuming your data is already in the right order if it's a category group.</p>

CC BY-SA 4.0
2021-04-27T05:46:25.190Z
Thanks so much for this! So my categories are in the format of 2021/22, so I updated a bit to the following, but when I dd on `loyaltyScore` it's blank. I've not used reduce before so a bit unsure.

`{% set currentYear = now|date('Y') ~ '/' ~ now|date_modify("+1 year")|date('y') %}`
supazu
CC BY-SA 4.0
2021-04-28T08:21:58.110Z
Trying to do maths on something that's not a number is going to be tricky! You should look to convert the format into a proper number with just a single year. You could convert "2021/22" to "2021" using Twig's slice filter: `{{ '2021/22'|slice(4) }}`
James Smith
CC BY-SA 4.0
2021-04-30T01:04:45.477Z
Thanks for your help - looks like this one is a bit beyond me.
supazu
CC BY-SA 4.0
2021-04-23T17:08:35.680Z
2021-04-23T17:08:35.680Z
James Smith
<p>Pseudo-code:</p>
<ul>
<li><p>Fetch all category values, push the year string to an array.</p>
</li>
<li><p>Sort that array in descending order by value.</p>
</li>
<li><p>Initialise a counter, loop over the array, cast each value as an integer:</p>
<p>-- if first array value is same as the current year, increase a counter, otherwise break.</p>
<p>-- if loop year equals previous loop year minus 1, increase a counter otherwise break.</p>
</li>
</ul>
<p>Your loyalty value is the counter.</p>

CC BY-SA 4.0
2021-04-30T01:05:45.413Z
The code is the part I'm having trouble with 
supazu
CC BY-SA 4.0
2021-04-30T07:55:17.803Z
That's fairly straightforward PHP, trying to do it in Twig is just making things more complicated (and really, you should minimise the amount of logic/processing in a Twig template). It would be worth looking at creating a Twig filter in a Craft module, which you could pass the user's years history to, e.g. `currentUser.years|myfilter`
Wallace
CC BY-SA 4.0
2021-04-23T09:06:46.160Z
2021-04-23T09:06:46.160Z
Wallace
<p>I need to count the number of consecutive years a user has been a member of our organization. For example, if they've been a member from in 2018, 2019, 2020 and 2021, their loyalty will be 4 years.</p>
<p>If they've been a member in 2018, 2019 and 2021, their loyalty will be 1 year (they missed 2020.)</p>
<p>I'm currently using Categories to assign a year to Users in Craft to do the assignment of a year to a person.</p>
<p>Hope that makes sense. I would very much appreciate some help on how to tackle it!</p>

<categories><array>
Count number of consecutive years in category array
# Count number of consecutive years in category array

(Asked by: username_0 on 2021-04-23)

I need to count the number of consecutive years a user has been a member of our organization. For example, if they've been a member from in 2018, 2019, 2020 and 2021, their loyalty will be 4 years.

If they've been a member in 2018, 2019 and 2021, their loyalty will be 1 year (they missed 2020.)

I'm currently using Categories to assign a year to Users in Craft to do the assignment of a year to a person.

Hope that makes sense. I would very much appreciate some help on how to tackle it!

**Tags:** categories, array

---

## 2 answers

### Answer by username_1 on 2021-04-23. Score: 2

If you don't want to build a custom plugin, this would be a good time to use Twig's reduce filter, which takes a set of values and iterates over them to output a single value based on supplied logic.
Using Andy's answer as the basis might look like this (untested):
{% set currentYear = now|date('Y') %}

{% set loyaltyScore = currentUser.years.all()|reduce(
    (score, year) => 
        score == 0 and year == currentYear or 
        score > 0 and year == currentYear - 1 ?
        score + 1,
        0
) %}

I'm assuming your data is already in the right order if it's a category group.

> **Comments:**
> **username_0**: Thanks so much for this! So my categories are in the format of 2021/22, so I updated a bit to the following, but when I dd on `loyaltyScore` it's blank. I've not used reduce before so a bit unsure.  `{% set currentYear = now|date('Y') ~ '/' ~ now|date_modify("+1 year")|date('y') %}`  
> **username_1**: Trying to do maths on something that's not a number is going to be tricky! You should look to convert the format into a proper number with just a single year. You could convert "2021/22" to "2021" using Twig's slice filter: `{{ '2021/22'|slice(4) }}`  
> **username_0**: Thanks for your help - looks like this one is a bit beyond me.  

---

### Answer by username_2 on 2021-04-23. Score: 1

Pseudo-code:

* Fetch all category values, push the year string to an array.
* Sort that array in descending order by value.
* Initialise a counter, loop over the array, cast each value as an integer:

  -- if first array value is same as the current year, increase a counter, otherwise break.

  -- if loop year equals previous loop year minus 1, increase a counter otherwise break.

Your loyalty value is the counter.

> **Comments:**
> **username_0**: The code is the part I'm having trouble with   
> **username_2**: That's fairly straightforward PHP, trying to do it in Twig is just making things more complicated (and really, you should minimise the amount of logic/processing in a Twig template). It would be worth looking at creating a Twig filter in a Craft module, which you could pass the user's years history to, e.g. `currentUser.years|myfilter`  

---

