Answers.Body: <p>This could also be accomplished with the <a href="https://twig.symfony.com/doc/2.x/filters/map.html" rel="noreferrer">map</a> filter, if you’re running Craft 3.1.29 or later:</p>
  <pre><code>{% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  
  {% set users = users|map(u =&gt; u.name == 'Tim' ? u|merge({age: 31}) : u) %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-10-20T13:59:23.420Z
Answers.Text: I like this solution. Thank you!
Answers.UserDisplayName: Mark Notton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-07T13:52:43.943Z
Answers.LastActivityDate: 2020-10-07T13:52:43.943Z
Answers.UserDisplayName: Brandon Kelly
Answers.Body: <p>A little bit nasty but you could do it like this (I could not find anything else)<br>
  Create this function in your plugins Variable</p>
  
  <pre><code>/**
   * @param array $array The array to modify
   * @param string $path The path in the array
   * @param mixed $value The value to set
   * @param string $delimiter The separator for the path
   * @return The new array
   */
  function setNestedArrayValue($array, $path, $value, $delimiter = '/') {
      $pathParts = explode($delimiter, $path);
  
      $current = &amp;$array;
      foreach($pathParts as $key) {
          $current = &amp;$current[$key];
      }
      $current = $value;
  
      return $array;
  }
  </code></pre>
  
  <p>Then you have this in your twig template</p>
  
  <pre><code> {% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  
  {% set users = craft.pluginHandle.setNestedArrayValue(users, '0/age', 40) %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-27T21:17:42.093Z
Answers.Text: I was hoping to do this in Twig.  If the answer is that it can't be done in Twig, that would be good to have documented somewhere, and I could accept that as the answer. Maybe an alternative Twig array setup would be nice to see, even if it means sacrificing some flexibility in my example.  I think a plugin is a bit overkill.
Answers.UserDisplayName: Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-27T21:21:19.337Z
Answers.Text: Why overkill? It takes only about 1 min to create the plugin. Don't get me wrong, I don't want to defend my answer or something, I just don't understand why so many people refuse to use a plugin in craft. A plugin doesn't even make your code noticeable slower.
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-29T18:24:43.277Z
Answers.Text: Well although a plugin is a solution, it's not really the answer to the question. And although I understand that Twig was not meant for heavy logic, sometimes you just need to change a value in a custom associative array like this and I don't want to add another plugin to the group just to do a simple task if I can help it.  If this were a part of a greater chunk of logic, then sure, write a plugin and do it in php.
Answers.UserDisplayName: Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-29T18:26:55.390Z
Answers.Text: Well then you can't solve your problem. It's not intended to do such things in twig. So the answer is: you can't do it in twig alone
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-29T21:53:58.720Z
Answers.Text: I think you can do this in Twig, but you have to adjust the `users` array to be a hash. A dynamic solution is presented in my answer I posted.
Answers.UserDisplayName: Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-27T20:05:55.320Z
Answers.LastActivityDate: 2017-10-27T20:57:48.380Z
Answers.LastEditDate: 2017-10-27T20:57:48.380Z
Answers.UserDisplayName: Robin Schambach
Answers.Body: <p>Did you try something like:</p>
  
  <pre><code>{% set users[1]['age'] = 31 %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-29T21:49:09.210Z
Answers.Text: No, this results in an error saying `Unexpected token "punctuation" of value "[" ("end of statement block" expected).` Twig makes you use its `merge` filter to change values in an array or hash (associative array).
Answers.UserDisplayName: Ryan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-28T21:58:57.427Z
Answers.LastActivityDate: 2017-10-28T21:58:57.427Z
Answers.UserDisplayName: Jim Wyse
Answers.Body: <h3>Solution</h3>
  
  <p>This won't work in Twig as presented in the question (see why below). Instead, <code>users</code> would need to be changed to an associative array (or "hash" in Twig terminology) with keys <em>that aren't integers</em>, and you'd have to insert a <code>merge</code> inside a <code>merge</code> to change the value:</p>
  
  <pre><code>{% set users = {
      person0: {name: 'Bill', age: 25},
      person1: {name: 'Tim', age: 30},
      person2: {name: 'John', age: 32}
  } %}
  
  {% set users = users|merge({ person1: users.person1|merge({age: 1000}) }) %}
  
  {% for key, user in users %}
      {{ key }}: {{ user.name }}, {{ user.age }}&lt;br&gt;
  {% endfor %}
  </code></pre>
  
  <p>...which now outputs:</p>
  
  <pre><code>person0: Bill, 25
  person1: Tim, 1000
  person2: John, 32
  </code></pre>
  
  <p>If you need to change the keys' integers dynamically, you will write it like this using Twig's <a href="https://twig.symfony.com/doc/2.x/functions/attribute.html" rel="noreferrer"><code>attribute</code></a> function and using brackets:</p>
  
  <pre><code>{% set loopIndex = 1 %}
  {% set users = users|merge({ ('person' ~ loopIndex): attribute(users, 'person' ~ loopIndex)|merge({age: 1000}) }) %}
  </code></pre>
  
  <hr>
  
  <h3>The Reason Why the Question's Array Doesn't Work</h3>
  
  <p>Twig's <code>merge</code> filter uses PHP's <code>array_merge</code> function, and according to PHP's docs when using <a href="http://php.net/manual/en/function.array-merge.php" rel="noreferrer"><code>array_merge</code></a>:</p>
  
  <blockquote>
    <p>If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, <strong>but will be appended</strong>.</p>
  </blockquote>
  
  <p>So trying to overwrite an existing hash in the original array</p>
  
  <pre><code>{% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %} 
  </code></pre>
  
  <p>...will just add the hash as a new, fourth item in the array, not replace the second one.  To demonstrate this clearer, we can rewrite <code>users</code> as a hash like this (it's considered the same as above):</p>
  
  <pre><code>{% set users = {
      0: {name: 'Bill', age: 25},
      1: {name: 'Tim', age: 30},
      2: {name: 'John', age: 32}
  } %}
  </code></pre>
  
  <p>By trying to target the key <code>1</code> to change its hash and output <code>users</code>:</p>
  
  <pre><code>{% set users = users|merge([ users.1|merge({age: 1000}) ]) %}
  
  {% for key, user in users %}
      {{ key }}: {{ user.name }}, {{ user.age }}&lt;br&gt;
  {% endfor %}
  </code></pre>
  
  <p>...we get this list:</p>
  
  <pre><code>0: Bill, 25
  1: Tim, 30
  2: John, 32
  3: Tim, 1000
  </code></pre>
  
  <p>A new "Tim" user will get appended even if you make the keys strings like <code>'0'</code>, <code>'1'</code>, etc, or using Twig's <code>attribute</code> function. <a href="https://github.com/twigphp/Twig/issues/789" rel="noreferrer">An issue for this</a> was posted in Twig's github and the conversation explains it some more. You can only change a value if it's an array with a list of single values (not a hash) or if it's a key/value hash, and the key can't be an integer.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-29T21:46:41.510Z
Answers.LastActivityDate: 2017-10-29T22:02:07.303Z
Answers.LastEditDate: 2017-10-29T22:02:07.303Z
Answers.UserDisplayName: Ryan
Body: <p>I'm strangely having trouble with this simple Twig merge problem and can't find anything online. Simplified, let's say you had:</p>
  
  <pre><code>{% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  </code></pre>
  
  <p>How would you change, for example, Tim's age from 30 to 31?  I've tried:</p>
  
  <pre><code>{% set users = users[1]|merge({age: 31}) %}
  {{ users[1].name }}: {{ users[1].age }}
  </code></pre>
  
  <p>But this doesn't work.</p>
  
Tags: <templating><array><merge>
Title: Overwrite value in object in array
ThreadText: # Overwrite value in object in array
  
  (Asked by: username_0 on 2017-10-27)
  
  I'm strangely having trouble with this simple Twig merge problem and can't find anything online. Simplified, let's say you had:
  
  ```
  {% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  
  ```
  
  How would you change, for example, Tim's age from 30 to 31? I've tried:
  
  ```
  {% set users = users[1]|merge({age: 31}) %}
  {{ users[1].name }}: {{ users[1].age }}
  
  ```
  
  But this doesn't work.
  
  **Tags:** templating, array, merge
  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_0 on 2017-10-29. Score: 13 | Accepted answer
  
  ### Solution
  
  This won't work in Twig as presented in the question (see why below). Instead, `users` would need to be changed to an associative array (or "hash" in Twig terminology) with keys *that aren't integers*, and you'd have to insert a `merge` inside a `merge` to change the value:
  
  ```
  {% set users = {
      person0: {name: 'Bill', age: 25},
      person1: {name: 'Tim', age: 30},
      person2: {name: 'John', age: 32}
  } %}
  
  {% set users = users|merge({ person1: users.person1|merge({age: 1000}) }) %}
  
  {% for key, user in users %}
      {{ key }}: {{ user.name }}, {{ user.age }}<br>
  {% endfor %}
  
  ```
  
  ...which now outputs:
  
  ```
  person0: Bill, 25
  person1: Tim, 1000
  person2: John, 32
  
  ```
  
  If you need to change the keys' integers dynamically, you will write it like this using Twig's [`attribute`](https://twig.symfony.com/doc/2.x/functions/attribute.html) function and using brackets:
  
  ```
  {% set loopIndex = 1 %}
  {% set users = users|merge({ ('person' ~ loopIndex): attribute(users, 'person' ~ loopIndex)|merge({age: 1000}) }) %}
  
  ```
  
  ---
  
  ### The Reason Why the Question's Array Doesn't Work
  
  Twig's `merge` filter uses PHP's `array_merge` function, and according to PHP's docs when using [`array_merge`](http://php.net/manual/en/function.array-merge.php):
  
  > If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, **but will be appended**.
  
  So trying to overwrite an existing hash in the original array
  
  ```
  {% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %} 
  
  ```
  
  ...will just add the hash as a new, fourth item in the array, not replace the second one. To demonstrate this clearer, we can rewrite `users` as a hash like this (it's considered the same as above):
  
  ```
  {% set users = {
      0: {name: 'Bill', age: 25},
      1: {name: 'Tim', age: 30},
      2: {name: 'John', age: 32}
  } %}
  
  ```
  
  By trying to target the key `1` to change its hash and output `users`:
  
  ```
  {% set users = users|merge([ users.1|merge({age: 1000}) ]) %}
  
  {% for key, user in users %}
      {{ key }}: {{ user.name }}, {{ user.age }}<br>
  {% endfor %}
  
  ```
  
  ...we get this list:
  
  ```
  0: Bill, 25
  1: Tim, 30
  2: John, 32
  3: Tim, 1000
  
  ```
  
  A new "Tim" user will get appended even if you make the keys strings like `'0'`, `'1'`, etc, or using Twig's `attribute` function. [An issue for this](https://github.com/twigphp/Twig/issues/789) was posted in Twig's github and the conversation explains it some more. You can only change a value if it's an array with a list of single values (not a hash) or if it's a key/value hash, and the key can't be an integer.
  
  
  ---
  
  ### Answer by username_1 on 2020-10-07. Score: 5
  
  This could also be accomplished with the [map](https://twig.symfony.com/doc/2.x/filters/map.html) filter, if you’re running Craft 3.1.29 or later:
  
  ```
  {% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  
  {% set users = users|map(u => u.name == 'Tim' ? u|merge({age: 31}) : u) %}
  
  ```
  
  > **Comments:**
  > **username_2**: I like this solution. Thank you!  
  
  ---
  
  ### Answer by username_3 on 2017-10-27. Score: 0
  
  A little bit nasty but you could do it like this (I could not find anything else)  
  Create this function in your plugins Variable
  
  ```
  /**
   * @param array $array The array to modify
   * @param string $path The path in the array
   * @param mixed $value The value to set
   * @param string $delimiter The separator for the path
   * @return The new array
   */
  function setNestedArrayValue($array, $path, $value, $delimiter = '/') {
      $pathParts = explode($delimiter, $path);
  
      $current = &$array;
      foreach($pathParts as $key) {
          $current = &$current[$key];
      }
      $current = $value;
  
      return $array;
  }
  
  ```
  
  Then you have this in your twig template
  
  ```
   {% set users = [
      {name: 'Bill', age: 25},
      {name: 'Tim', age: 30},
      {name: 'John', age: 32}
  ] %}
  
  {% set users = craft.pluginHandle.setNestedArrayValue(users, '0/age', 40) %}
  
  ```
  
  > **Comments:**
  > **username_0**: I was hoping to do this in Twig.  If the answer is that it can't be done in Twig, that would be good to have documented somewhere, and I could accept that as the answer. Maybe an alternative Twig array setup would be nice to see, even if it means sacrificing some flexibility in my example.  I think a plugin is a bit overkill.  
  > **username_3**: Why overkill? It takes only about 1 min to create the plugin. Don't get me wrong, I don't want to defend my answer or something, I just don't understand why so many people refuse to use a plugin in craft. A plugin doesn't even make your code noticeable slower.  
  > **username_0**: Well although a plugin is a solution, it's not really the answer to the question. And although I understand that Twig was not meant for heavy logic, sometimes you just need to change a value in a custom associative array like this and I don't want to add another plugin to the group just to do a simple task if I can help it.  If this were a part of a greater chunk of logic, then sure, write a plugin and do it in php.  
  > **username_3**: Well then you can't solve your problem. It's not intended to do such things in twig. So the answer is: you can't do it in twig alone  
  > **username_0**: I think you can do this in Twig, but you have to adjust the `users` array to be a hash. A dynamic solution is presented in my answer I posted.  
  
  ---
  
  ### Answer by username_4 on 2017-10-28. Score: -1
  
  Did you try something like:
  
  ```
  {% set users[1]['age'] = 31 %}
  
  ```
  
  > **Comments:**
  > **username_0**: No, this results in an error saying `Unexpected token "punctuation" of value "[" ("end of statement block" expected).` Twig makes you use its `merge` filter to change values in an array or hash (associative array).  
  
  ---
  
  