Nested templated data: Difference between revisions

From Rosetta Code
Content added Content deleted
m (syntax highlighting fixup automation)
Line 13: Line 13:
;Task Detail:
;Task Detail:
Given the following input template <code>t</code> and list of payloads <code>p</code>:
Given the following input template <code>t</code> and list of payloads <code>p</code>:
<lang># Square brackets are used here to denote nesting but may be changed for other,
<syntaxhighlight lang="text"># Square brackets are used here to denote nesting but may be changed for other,
# clear, visual representations of nested data appropriate to ones programming
# clear, visual representations of nested data appropriate to ones programming
# language.
# language.
Line 21: Line 21:
5]]
5]]


p = 'Payload#0' ... 'Payload#6'</lang>
p = 'Payload#0' ... 'Payload#6'</syntaxhighlight>


The correct output should have the following structure, (although spacing and
The correct output should have the following structure, (although spacing and
linefeeds may differ, the nesting and order should follow):
linefeeds may differ, the nesting and order should follow):
<lang>[[['Payload#1', 'Payload#2'],
<syntaxhighlight lang="text">[[['Payload#1', 'Payload#2'],
['Payload#3', 'Payload#4', 'Payload#1'],
['Payload#3', 'Payload#4', 'Payload#1'],
'Payload#5']]</lang>
'Payload#5']]</syntaxhighlight>


1. Generate the output for the above template, <code>t</code>.<br>
1. Generate the output for the above template, <code>t</code>.<br>
Line 38: Line 38:


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
<lang AutoHotkey>;-----------------------------------------------------------
<syntaxhighlight lang="autohotkey">;-----------------------------------------------------------
Nested_templated_data(template, Payload){
Nested_templated_data(template, Payload){
UsedP := [], UnusedP := [], UnusedI := []
UsedP := [], UnusedP := [], UnusedI := []
Line 82: Line 82:
return nobj
return nobj
}
}
;-----------------------------------------------------------</lang>
;-----------------------------------------------------------</syntaxhighlight>
Examples:<lang AutoHotkey>T := [[[1,2] , [3,4,1] , 5]]
Examples:<syntaxhighlight lang="autohotkey">T := [[[1,2] , [3,4,1] , 5]]
; Autohotkey uses 1-based objects/arrays
; Autohotkey uses 1-based objects/arrays
P := ["Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6", "Payload#7"]
P := ["Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6", "Payload#7"]
Line 89: Line 89:
output := Results.1
output := Results.1
Undefined_indices := Results[2]
Undefined_indices := Results[2]
Unused_Payloads := Results[3]</lang>
Unused_Payloads := Results[3]</syntaxhighlight>
{{out}}
{{out}}
<pre>T := [[[1,2] , [3,4,1] , 5]]
<pre>T := [[[1,2] , [3,4,1] , 5]]
Line 105: Line 105:
=={{header|Bracmat}}==
=={{header|Bracmat}}==
The uninstantiated template and the instantiated template are JSON structures. The payloads are listed in a Bracmat list. The <code>get</code> function is instructed to read input from memory and to parse it as JSON. The output of this call is a Bracmat structure (not shown) that is assigned to <code>template</code>. The <code>instantiate</code> function recursively traverses the template's tree structure. If the current node is a number, then that number is used as the key into the payloads list. The corresponding payload is then returned. If the current node is not a number, then it is assumed that the current node is a binary (sub)tree. The left hand side (called <code>a</code>) and the right hand side (called <code>b</code>) are instantiated and their combination is returned. Finally the instantiated tree is transformed back to JSON format and output.
The uninstantiated template and the instantiated template are JSON structures. The payloads are listed in a Bracmat list. The <code>get</code> function is instructed to read input from memory and to parse it as JSON. The output of this call is a Bracmat structure (not shown) that is assigned to <code>template</code>. The <code>instantiate</code> function recursively traverses the template's tree structure. If the current node is a number, then that number is used as the key into the payloads list. The corresponding payload is then returned. If the current node is not a number, then it is assumed that the current node is a binary (sub)tree. The left hand side (called <code>a</code>) and the right hand side (called <code>b</code>) are instantiated and their combination is returned. Finally the instantiated tree is transformed back to JSON format and output.
<lang bracmat>( get$("[
<syntaxhighlight lang="bracmat">( get$("[
[[1, 2],
[[1, 2],
[3, 4, 1],
[3, 4, 1],
Line 129: Line 129:
)
)
& out$(jsn$(instantiate$(!template.!payloads)))
& out$(jsn$(instantiate$(!template.!payloads)))
);</lang>
);</syntaxhighlight>
{{out}}
{{out}}
<pre>[[[payload#1,payload#2],[payload#3,payload#4,payload#1],payload#5]]</pre>
<pre>[[[payload#1,payload#2],[payload#3,payload#4,payload#1],payload#5]]</pre>
Line 138: Line 138:
The nested indexes are defined by tuples from the standard library. C++ function templates recursively traverse the tuple structure and map to the payloads.
The nested indexes are defined by tuples from the standard library. C++ function templates recursively traverse the tuple structure and map to the payloads.


<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">#include <iostream>
#include <set>
#include <set>
#include <tuple>
#include <tuple>
Line 224: Line 224:
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 246: Line 246:


=={{header|Crystal}}==
=={{header|Crystal}}==
<lang Ruby>def with_payload(template, payload, used = nil)
<syntaxhighlight lang="ruby">def with_payload(template, payload, used = nil)
template.map do |item|
template.map do |item|
if item.is_a? Enumerable
if item.is_a? Enumerable
Line 263: Line 263:


unused = Set(Int32).new((0..6).to_a) - used
unused = Set(Int32).new((0..6).to_a) - used
puts "Unused indices: #{unused}"</lang>
puts "Unused indices: #{unused}"</syntaxhighlight>


{{out}}
{{out}}
Line 271: Line 271:
=={{header|Factor}}==
=={{header|Factor}}==
Words for traversing nested sequences can be found in the <code>sequences.deep</code> vocabulary. Factor's prettyprinter attempts to print structures on a single line (64 characters by default, though this can be changed) if they will fit. Otherwise, the prettyprinter will break them up into multiple lines, preferring to show one member per line if possible. <code>f</code>, Factor's false/nil value, is used to indicate a missing payload.
Words for traversing nested sequences can be found in the <code>sequences.deep</code> vocabulary. Factor's prettyprinter attempts to print structures on a single line (64 characters by default, though this can be changed) if they will fit. Otherwise, the prettyprinter will break them up into multiple lines, preferring to show one member per line if possible. <code>f</code>, Factor's false/nil value, is used to indicate a missing payload.
<lang factor>USING: formatting kernel literals math sequences sequences.deep ;
<syntaxhighlight lang="factor">USING: formatting kernel literals math sequences sequences.deep ;
IN: rosetta-code.nested-template-data
IN: rosetta-code.nested-template-data


Line 288: Line 288:
[ dup insert-payloads "Template: %u\nData Structure: %u\n"
[ dup insert-payloads "Template: %u\nData Structure: %u\n"
printf ] bi@</lang>
printf ] bi@</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 312: Line 312:
Go's standard library includes a "text/template" package which can be used for this task.
Go's standard library includes a "text/template" package which can be used for this task.
<br>
<br>
The integer indices are represented by the keys of a map whose corresponding value is the appropriate payload string. Templates have their own mini-language and, for a map P with key n, the expression: <lang html>{{index .P n}}</lang> will be replaced by the corresponding payload.
The integer indices are represented by the keys of a map whose corresponding value is the appropriate payload string. Templates have their own mini-language and, for a map P with key n, the expression: <syntaxhighlight lang="html">{{index .P n}}</syntaxhighlight> will be replaced by the corresponding payload.
<br>
<br>
If an integer index either doesn't exist in the map or maps to an empty payload, then the above expression will simply be replaced by an empty string when the template is executed.
If an integer index either doesn't exist in the map or maps to an empty payload, then the above expression will simply be replaced by an empty string when the template is executed.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 350: Line 350:
sort.Ints(unused)
sort.Ints(unused)
fmt.Println("\nThe unused payloads have indices of :", unused)
fmt.Println("\nThe unused payloads have indices of :", unused)
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 372: Line 372:
If we do not bother about neat textual representation, the definition of traversable nested template is as easy as following:
If we do not bother about neat textual representation, the definition of traversable nested template is as easy as following:


<lang haskell>{-# language DeriveTraversable #-}
<syntaxhighlight lang="haskell">{-# language DeriveTraversable #-}


data Template a = Val a | List [Template a]
data Template a = Val a | List [Template a]
Line 378: Line 378:
, Functor
, Functor
, Foldable
, Foldable
, Traversable )</lang>
, Traversable )</syntaxhighlight>


Functorial property of a data type is sufficient for defining the universal substitutor of keys/indices by payload data:
Functorial property of a data type is sufficient for defining the universal substitutor of keys/indices by payload data:
<lang haskell>subst :: (Functor t, Eq i) => [(i,a)] -> t i -> t (Maybe a)
<syntaxhighlight lang="haskell">subst :: (Functor t, Eq i) => [(i,a)] -> t i -> t (Maybe a)
subst d = fmap (`lookup` d)</lang>
subst d = fmap (`lookup` d)</syntaxhighlight>


It is possible to turn any list of payloads into a map by simple helper function:
It is possible to turn any list of payloads into a map by simple helper function:


<lang haskell>indexed :: [a] -> [(Int, a)]
<syntaxhighlight lang="haskell">indexed :: [a] -> [(Int, a)]
indexed = zip [0..]</lang>
indexed = zip [0..]</syntaxhighlight>


Now we can make substitutions to flat lists or nested templates:
Now we can make substitutions to flat lists or nested templates:


<lang haskell>t :: Template Int
<syntaxhighlight lang="haskell">t :: Template Int
t = List [ List [Val 1, Val 2]
t = List [ List [Val 1, Val 2]
, List [Val 3, Val 4, Val 10]
, List [Val 3, Val 4, Val 10]
Line 397: Line 397:


payloads :: [(Int, String)]
payloads :: [(Int, String)]
payloads = [(i, "payload#"++show i) | i <- [0..6]]</lang>
payloads = [(i, "payload#"++show i) | i <- [0..6]]</syntaxhighlight>


<pre>λ> subst payloads [6,2,1,2]
<pre>λ> subst payloads [6,2,1,2]
Line 426: Line 426:
Foldable properties of templates (with a little help of monoids) allow to implement extended tasks.
Foldable properties of templates (with a little help of monoids) allow to implement extended tasks.


<lang haskell>unusedIndices :: (Foldable t, Eq i) => [(i,a)] -> t i -> [i]
<syntaxhighlight lang="haskell">unusedIndices :: (Foldable t, Eq i) => [(i,a)] -> t i -> [i]
unusedIndices d = foldMap unused
unusedIndices d = foldMap unused
where unused i = maybe (pure i) (pure []) $ lookup i d
where unused i = maybe (pure i) (pure []) $ lookup i d
Line 432: Line 432:
unusedData :: (Foldable t, Eq i) => [(i, a)] -> t i -> [(i,a)]
unusedData :: (Foldable t, Eq i) => [(i, a)] -> t i -> [(i,a)]
unusedData = foldr delete
unusedData = foldr delete
where delete i = filter ((i /= ) . fst) </lang>
where delete i = filter ((i /= ) . fst) </syntaxhighlight>


<pre>λ> unusedIndices payloads t
<pre>λ> unusedIndices payloads t
Line 642: Line 642:


For the main task, the key ideas here are (1) to use a JSON dictionary to store the integer-to-payload mapping; and (2) to use the built-in filter, `walk/1`, to instantiate the template.
For the main task, the key ideas here are (1) to use a JSON dictionary to store the integer-to-payload mapping; and (2) to use the built-in filter, `walk/1`, to instantiate the template.
<syntaxhighlight lang="sh">
<lang sh>
#!/bin/bash
#!/bin/bash
function template {
function template {
Line 665: Line 665:
| walk(if type == "number" then $dict[tostring] else . end)
| walk(if type == "number" then $dict[tostring] else . end)
'
'
</syntaxhighlight>
</lang>
This produces the expected output, as also shown below.
This produces the expected output, as also shown below.


For the second task, we could separately invoke jq similarly:
For the second task, we could separately invoke jq similarly:
<syntaxhighlight lang="sh">
<lang sh>
payload | jq -Rn --argfile t <(template) '
payload | jq -Rn --argfile t <(template) '
([inputs] | with_entries(.key |= tostring)) as $dict
([inputs] | with_entries(.key |= tostring)) as $dict
| $dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
| $dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
'
'
</syntaxhighlight>
</lang>


Or, if you prefer one invocation of jq for both tasks:<lang sh>
Or, if you prefer one invocation of jq for both tasks:<syntaxhighlight lang="sh">
payload | jq -Rrn --argfile t <(template) '
payload | jq -Rrn --argfile t <(template) '
([inputs] | with_entries(.key |= tostring)) as $dict
([inputs] | with_entries(.key |= tostring)) as $dict
Line 683: Line 683:
"\nUnused payload",
"\nUnused payload",
$dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
$dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
'</lang>
'</syntaxhighlight>
{{out}}
{{out}}
<lang sh>[
<syntaxhighlight lang="sh">[
[
[
[
[
Line 702: Line 702:
Unused payload
Unused payload
Payload#0
Payload#0
Payload#6</lang>
Payload#6</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
The array structure needs to be specified as Any type of data, to allow assignment of String to positions in the array originally containing integers.
The array structure needs to be specified as Any type of data, to allow assignment of String to positions in the array originally containing integers.
<lang julia>t = ([Any[Any[1, 2],
<syntaxhighlight lang="julia">t = ([Any[Any[1, 2],
Any[3, 4, 1],
Any[3, 4, 1],
5]])
5]])
Line 732: Line 732:


show(t)
show(t)
</lang>{{output}}<pre>
</syntaxhighlight>{{output}}<pre>
Array{Any,1}[[Any["Payload#1", "Payload#2"], Any["Payload#3", "Payload#4", "Payload#1"], "Payload#5"]]
Array{Any,1}[[Any["Payload#1", "Payload#2"], Any["Payload#3", "Payload#4", "Payload#1"], "Payload#5"]]
</pre>
</pre>


=={{header|Mathematica}}/{{header|Wolfram Language}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<lang Mathematica>t = ToExpression[StringReplace["[[[1,2],[3,4,1],5]]", {"[" -> "{", "]" -> "}"}]];
<syntaxhighlight lang="mathematica">t = ToExpression[StringReplace["[[[1,2],[3,4,1],5]]", {"[" -> "{", "]" -> "}"}]];
p = "Payload#" <> ToString[#] & /@ Range[6];
p = "Payload#" <> ToString[#] & /@ Range[6];
Map[p[[#]] &, t, {-1}]</lang>
Map[p[[#]] &, t, {-1}]</syntaxhighlight>
{{out}}
{{out}}
<pre>{{{"Payload#1", "Payload#2"}, {"Payload#3", "Payload#4", "Payload#1"}, "Payload#5"}}</pre>
<pre>{{{"Payload#1", "Payload#2"}, {"Payload#3", "Payload#4", "Payload#1"}, "Payload#5"}}</pre>
Line 745: Line 745:


=={{header|M2000 Interpreter}}==
=={{header|M2000 Interpreter}}==
<lang M2000 Interpreter>Font "Courier New"
<syntaxhighlight lang="m2000 interpreter">Font "Courier New"
cls
cls
Module Checkit {
Module Checkit {
Line 891: Line 891:
}
}
Checkit
Checkit
Report clipboard$</lang>
Report clipboard$</syntaxhighlight>
{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll">Payloads:
<pre style="height:30ex;overflow:scroll">Payloads:
Line 937: Line 937:


=={{header|Nim}}==
=={{header|Nim}}==
<lang nim>import macros,sugar,strformat
<syntaxhighlight lang="nim">import macros,sugar,strformat
#macro to take a nested tuple and return a type
#macro to take a nested tuple and return a type
#e.g. (int,(int,int))=>(string,(string,string))
#e.g. (int,(int,int))=>(string,(string,string))
Line 964: Line 964:
let tplt2 = ((1,2),(3,4,1),6)
let tplt2 = ((1,2),(3,4,1),6)
echo replace(tplt1, p)
echo replace(tplt1, p)
echo replace(tplt2, p)</lang>
echo replace(tplt2, p)</syntaxhighlight>
{{out}}
{{out}}
<pre>(("payload1", "payload2"), ("payload3", "payload4", "payload1"), "payload5")
<pre>(("payload1", "payload2"), ("payload3", "payload4", "payload1"), "payload5")
Line 971: Line 971:
=={{header|Perl}}==
=={{header|Perl}}==
Only handles nesting one level deep. Missing data is <code>undef</code> in the data structure, an empty string in the pretty-printer.
Only handles nesting one level deep. Missing data is <code>undef</code> in the data structure, an empty string in the pretty-printer.
<lang perl>sub fulfill {
<syntaxhighlight lang="perl">sub fulfill {
my @payloads;
my @payloads;
push @payloads, 'Payload#' . $_ for 0..5;
push @payloads, 'Payload#' . $_ for 0..5;
Line 987: Line 987:
print formatted fulfill( [[1,2], [ 3,4,1], 5] );
print formatted fulfill( [[1,2], [ 3,4,1], 5] );
print formatted fulfill( [[1,2], [10,4,1], 5] );
print formatted fulfill( [[1,2], [10,4,1], 5] );
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>[ [ "Payload#1", "Payload#2" ], [ "Payload#3", "Payload#4", "Payload#1" ], "Payload#5" ]
<pre>[ [ "Payload#1", "Payload#2" ], [ "Payload#3", "Payload#4", "Payload#1" ], "Payload#5" ]
Line 993: Line 993:


===Arbitrary Nesting===
===Arbitrary Nesting===
<lang perl>#!/usr/bin/perl
<syntaxhighlight lang="perl">#!/usr/bin/perl


use strict; # https://rosettacode.org/wiki/Nested_templated_data
use strict; # https://rosettacode.org/wiki/Nested_templated_data
Line 1,014: Line 1,014:
my ($t, $p) = @_;
my ($t, $p) = @_;
return ref $t eq 'ARRAY' ? [ map filltemplate($_, $p), @$t ] : $p->[$t];
return ref $t eq 'ARRAY' ? [ map filltemplate($_, $p), @$t ] : $p->[$t];
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,044: Line 1,044:


Note that Phix indexes are normally 1-based, but to better match the task description those in the templates are 0-based
Note that Phix indexes are normally 1-based, but to better match the task description those in the templates are 0-based
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">constant</span> <span style="color: #000000;">template</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">},</span> <span style="color: #000000;">5</span> <span style="color: #0000FF;">}</span> <span style="color: #0000FF;">},</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">template</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">},</span> <span style="color: #000000;">5</span> <span style="color: #0000FF;">}</span> <span style="color: #0000FF;">},</span>
<span style="color: #000000;">template2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">},</span> <span style="color: #000000;">5</span> <span style="color: #0000FF;">}</span> <span style="color: #0000FF;">},</span>
<span style="color: #000000;">template2</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span> <span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">},</span> <span style="color: #000000;">5</span> <span style="color: #0000FF;">}</span> <span style="color: #0000FF;">},</span>
Line 1,079: Line 1,079:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Missing payloads: %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">missing</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Missing payloads: %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">missing</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
<pre>
<pre>
{{{"Payload#1", "Payload#2"},
{{{"Payload#1", "Payload#2"},
Line 1,098: Line 1,098:


A distinctive string is used to indicate missing payloads.
A distinctive string is used to indicate missing payloads.
<lang python>from pprint import pprint as pp
<syntaxhighlight lang="python">from pprint import pprint as pp


class Template():
class Template():
Line 1,146: Line 1,146:
print(" MISSING PAYLOADS:\n ", end='')
print(" MISSING PAYLOADS:\n ", end='')
missed = t.missed_payloads
missed = t.missed_payloads
print('\n '.join(missed) if missed else '-')</lang>
print('\n '.join(missed) if missed else '-')</syntaxhighlight>


{{out}}
{{out}}
Line 1,197: Line 1,197:
This is a fairly straightforward implementation in R using a recursive function. It's not likely the most efficient in the world.
This is a fairly straightforward implementation in R using a recursive function. It's not likely the most efficient in the world.


<lang R>fill_template <- function(x, template, prefix = "Payload#") {
<syntaxhighlight lang="r">fill_template <- function(x, template, prefix = "Payload#") {
for (i in seq_along(template)) {
for (i in seq_along(template)) {
temp_slice <- template[[i]]
temp_slice <- template[[i]]
Line 1,220: Line 1,220:
toJSON(payload, auto_unbox = TRUE),
toJSON(payload, auto_unbox = TRUE),
toJSON(result, auto_unbox = TRUE)
toJSON(result, auto_unbox = TRUE)
))</lang>
))</syntaxhighlight>


{{out}}
{{out}}
Line 1,232: Line 1,232:
<code>rackunit</code> is used to test the outcomes of template application. So no output indicates expectations met (i.e. success).
<code>rackunit</code> is used to test the outcomes of template application. So no output indicates expectations met (i.e. success).


<lang racket>#lang racket
<syntaxhighlight lang="racket">#lang racket


(define current-not-found-handler
(define current-not-found-handler
Line 1,264: Line 1,264:


(parameterize ((current-not-found-handler (λ (idx max) (format "?~a" idx))))
(parameterize ((current-not-found-handler (λ (idx max) (format "?~a" idx))))
(check-equal? (out-of-bounds-generating-template-substitution p) '("?7"))))</lang>
(check-equal? (out-of-bounds-generating-template-substitution p) '("?7"))))</syntaxhighlight>


=={{header|Raku}}==
=={{header|Raku}}==
Line 1,270: Line 1,270:
{{works with|Rakudo|2020.08.1}}
{{works with|Rakudo|2020.08.1}}
Explicitly not using strings, using one data structure to fill in another. Since it ''isn't'' a string, the output format removes the newlines from the template; line feed (white space in general) isn't particularly significant in Raku data structures. It does preserve the nesting though. In the second example, payload "buckets" that don't exist result in an undefined value being inserted; by default: Any.
Explicitly not using strings, using one data structure to fill in another. Since it ''isn't'' a string, the output format removes the newlines from the template; line feed (white space in general) isn't particularly significant in Raku data structures. It does preserve the nesting though. In the second example, payload "buckets" that don't exist result in an undefined value being inserted; by default: Any.
<lang perl6>say join "\n ", '##PAYLOADS:', |my @payloads = 'Payload#' X~ ^7;
<syntaxhighlight lang="raku" line>say join "\n ", '##PAYLOADS:', |my @payloads = 'Payload#' X~ ^7;


for [
for [
Line 1,283: Line 1,283:
say "\n Template: ", $_.raku;
say "\n Template: ", $_.raku;
say "Data structure: { @payloads[|$_].raku }";
say "Data structure: { @payloads[|$_].raku }";
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>##PAYLOADS:
<pre>##PAYLOADS:
Line 1,302: Line 1,302:
=={{header|REXX}}==
=={{header|REXX}}==
===version 1===
===version 1===
<lang rexx>/* REXX */
<syntaxhighlight lang="rexx">/* REXX */
tok.=''
tok.=''
Do i=0 To 6
Do i=0 To 6
Line 1,407: Line 1,407:
End
End
Else
Else
Return "'Payload#" i "not defined'"</lang>
Return "'Payload#" i "not defined'"</syntaxhighlight>
{{out}}
{{out}}
<pre>Template [[[1,2],[3,4,1],5]]
<pre>Template [[[1,2],[3,4,1],5]]
Line 1,423: Line 1,423:


===version 2===
===version 2===
<lang rexx>/* REXX */
<syntaxhighlight lang="rexx">/* REXX */
tok.=''
tok.=''
Do i=0 To 6
Do i=0 To 6
Line 1,522: Line 1,522:


o: Say arg(1)
o: Say arg(1)
Return</lang>
Return</syntaxhighlight>
{{out}}
{{out}}
<pre>[[[1,2],[ 3,4,1],5]]
<pre>[[[1,2],[ 3,4,1],5]]
Line 1,551: Line 1,551:
=={{header|VBA}}==
=={{header|VBA}}==
VBA allows arrays of variant, so the elements of an array can be both scalars as arrays of different sizes.
VBA allows arrays of variant, so the elements of an array can be both scalars as arrays of different sizes.
<lang vb>Public Sub test()
<syntaxhighlight lang="vb">Public Sub test()
Dim t(2) As Variant
Dim t(2) As Variant
t(0) = [{1,2}]
t(0) = [{1,2}]
Line 1,579: Line 1,579:
If Not q(i) Then Debug.Print p(i + 1); " is not used"
If Not q(i) Then Debug.Print p(i + 1); " is not used"
Next i
Next i
End Sub</lang>{{out}}
End Sub</syntaxhighlight>{{out}}
<pre>Payload#1, Payload#2
<pre>Payload#1, Payload#2
Payload#3, Payload#4, Payload#1
Payload#3, Payload#4, Payload#1
Line 1,590: Line 1,590:
{{libheader|Wren-set}}
{{libheader|Wren-set}}
{{libheader|Wren-sort}}
{{libheader|Wren-sort}}
<lang ecmascript>import "/set" for Set
<syntaxhighlight lang="ecmascript">import "/set" for Set
import "/sort" for Sort
import "/sort" for Sort


Line 1,612: Line 1,612:
var unused = Set.new(0..6).except(Set.new(used)).toList
var unused = Set.new(0..6).except(Set.new(used)).toList
Sort.insertion(unused)
Sort.insertion(unused)
System.print("The unused payloads have indices of %(unused).")</lang>
System.print("The unused payloads have indices of %(unused).")</syntaxhighlight>


{{out}}
{{out}}
Line 1,627: Line 1,627:


Void is used as a marker for an unknown payload.
Void is used as a marker for an unknown payload.
<lang zkl>var payloads=[1..6].pump(List,"Payload#".append);
<syntaxhighlight lang="zkl">var payloads=[1..6].pump(List,"Payload#".append);


fcn get(n){ try{ payloads[n - 1] }catch{ Void } }
fcn get(n){ try{ payloads[n - 1] }catch{ Void } }
fcn sub(list){ list.pump(List, fcn(n){ if(n.isType(List)) sub(n) else get(n) }) }</lang>
fcn sub(list){ list.pump(List, fcn(n){ if(n.isType(List)) sub(n) else get(n) }) }</syntaxhighlight>
<lang zkl>foreach p in (T(
<syntaxhighlight lang="zkl">foreach p in (T(
T(T(T(1, 2),
T(T(T(1, 2),
T(3, 4, 1),
T(3, 4, 1),
Line 1,639: Line 1,639:
5),))){
5),))){
println(" Template: %s\nData structure: %s".fmt(p,sub(p)));
println(" Template: %s\nData structure: %s".fmt(p,sub(p)));
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>

Revision as of 23:45, 27 August 2022

Task
Nested templated data
You are encouraged to solve this task according to the task description, using any language you may know.

A template for data is an arbitrarily nested tree of integer indices.

Data payloads are given as a separate mapping, array or other simpler, flat, association of indices to individual items of data, and are strings.
The idea is to create a data structure with the templates' nesting, and the payload corresponding to each index appearing at the position of each index.

Answers using simple string replacement or regexp are to be avoided. The idea is to use the native, or usual implementation of lists/tuples etc of the language and to hierarchically traverse the template to generate the output.

Task Detail

Given the following input template t and list of payloads p:

# Square brackets are used here to denote nesting but may be changed for other,
# clear, visual representations of nested data appropriate to ones programming 
# language.
t = [
    [[1, 2],
     [3, 4, 1], 
     5]]

p = 'Payload#0' ... 'Payload#6'

The correct output should have the following structure, (although spacing and linefeeds may differ, the nesting and order should follow):

[[['Payload#1', 'Payload#2'],
  ['Payload#3', 'Payload#4', 'Payload#1'],
  'Payload#5']]

1. Generate the output for the above template, t.

Optional Extended tasks

2. Show which payloads remain unused.
3. Give some indication/handling of indices without a payload.

Show output on this page.

AutoHotkey

;-----------------------------------------------------------
Nested_templated_data(template, Payload){
	UsedP := [], UnusedP := [], UnusedI := []
	result := template.Clone()
	x := ArrMap(template, Payload, result, UsedP, UnusedI, [])
	for i, v in Payload
		if !UsedP[v]
			UnusedP.Push(v)
	return [x.1, x.2, UnusedP]
}
;-----------------------------------------------------------
ArrMap(Template, Payload, result, UsedP, UnusedI, pth){
	for i, index in Template	{
		if IsObject(index)
			pth.Push(i),	Arrmap(index, Payload, result, UsedP, UnusedI, pth)
		else{
			pth.Push(i),	ArrSetPath(result, pth, Payload[index])
			if Payload[index]
				UsedP[Payload[index]] := 1
			else
				UnusedI.Push(index)
		}
		pth.Pop()
	}
	return [result, UnusedI, UsedP]
}
;-----------------------------------------------------------
ArrSetPath(Arr, pth, newVal){
	temp := []
	for k, v in pth{
		temp.push(v)
		if !IsObject(Arr[temp*])
			Arr[temp*] := []
	}
	return Arr[temp*] := newVal
}
;-----------------------------------------------------------
objcopy(obj){
	nobj := obj.Clone()
	for k, v in nobj
		if IsObject(v)
			nobj[k] := objcopy(v)
	return nobj
}
;-----------------------------------------------------------

Examples:

T := [[[1,2] , [3,4,1] , 5]]
; Autohotkey uses 1-based objects/arrays
P := ["Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6", "Payload#7"]
Results := Nested_templated_data(objcopy(t), P)
output := Results.1
Undefined_indices := Results[2]
Unused_Payloads := Results[3]
Output:
T := [[[1,2] , [3,4,1] , 5]]
P := ["Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6", "Payload#7"]
output : [[["payload#1", "payload#2"] , ["payload#3", "payload#4", "payload#1"] , "payload#5"]]
Undefined_indices : []
Unused_Payloads : ["Payload#6", "Payload#7"]
;-----------------------------------------------------------
T := [[[1,2] , [3,4,1,8] , 5]]
P := ["Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6", "Payload#7"]
output : [[["payload#1", "payload#2"] , ["payload#3", "payload#4", "payload#1", ""] , "payload#5"]]
Undefined_indices : [8]
Unused_Payloads : ["Payload#6", "Payload#7"]

Bracmat

The uninstantiated template and the instantiated template are JSON structures. The payloads are listed in a Bracmat list. The get function is instructed to read input from memory and to parse it as JSON. The output of this call is a Bracmat structure (not shown) that is assigned to template. The instantiate function recursively traverses the template's tree structure. If the current node is a number, then that number is used as the key into the payloads list. The corresponding payload is then returned. If the current node is not a number, then it is assumed that the current node is a binary (sub)tree. The left hand side (called a) and the right hand side (called b) are instantiated and their combination is returned. Finally the instantiated tree is transformed back to JSON format and output.

(   get$("[
    [[1, 2],
     [3, 4, 1],
     5]]",MEM,JSN)
  : ?template
&     (0.payload#0)
      (1.payload#1)
      (2.payload#2)
      (3.payload#3)
      (4.payload#4)
      (5.payload#5)
      (6.payload#6)
  : ?payloads
& ( instantiate
  =   tmplt plds pld a b
    .   !arg:(?tmplt.?plds)
      & (   !tmplt:#
          & !plds:? (!tmplt.?pld) ?
          & !pld
        |   !tmplt:%?a_%?b
          & (instantiate$(!a.!plds))_(instantiate$(!b.!plds))
        )
  )
& out$(jsn$(instantiate$(!template.!payloads)))
);
Output:
[[[payload#1,payload#2],[payload#3,payload#4,payload#1],payload#5]]

C++

Uses C++17 or later.

The nested indexes are defined by tuples from the standard library. C++ function templates recursively traverse the tuple structure and map to the payloads.

#include <iostream>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

// print a single payload
template<typename P>
void PrintPayloads(const P &payloads, int index, bool isLast)
{
    if(index < 0 || index >= (int)size(payloads)) cout << "null";        
    else cout << "'" << payloads[index] << "'";
    if (!isLast) cout << ", ";  // add a comma between elements
}

// print a tuple of playloads
template<typename P, typename... Ts>
void PrintPayloads(const P &payloads, tuple<Ts...> const& nestedTuple, bool isLast = true)
{
    std::apply  // recursively call PrintPayloads on each element of the tuple
    (
        [&payloads, isLast](Ts const&... tupleArgs)
        {
            size_t n{0};
            cout << "[";
            (PrintPayloads(payloads, tupleArgs, (++n == sizeof...(Ts)) ), ...);
            cout << "]";
            cout << (isLast ? "\n" : ",\n");
        }, nestedTuple
    );
}

// find the unique index of a single index (helper for the function below)
void FindUniqueIndexes(set<int> &indexes, int index)
{
    indexes.insert(index);
}

// find the unique indexes in the tuples
template<typename... Ts>
void FindUniqueIndexes(set<int> &indexes, std::tuple<Ts...> const& nestedTuple)
{
    std::apply
    (
        [&indexes](Ts const&... tupleArgs)
        {
            (FindUniqueIndexes(indexes, tupleArgs),...);
        }, nestedTuple
    );
}

// print the payloads that were not used
template<typename P>
void PrintUnusedPayloads(const set<int> &usedIndexes, const P &payloads)
{
    for(size_t i = 0; i < size(payloads); i++)
    {
        if(usedIndexes.find(i) == usedIndexes.end() ) cout << payloads[i] << "\n";
    }
}

int main()
{
    // define the playloads, they can be in most containers
    vector payloads {"Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"};
    const char *shortPayloads[] {"Payload#0", "Payload#1", "Payload#2", "Payload#3"}; // as a C array

    // define the indexes as a nested tuple
    auto tpl = make_tuple(make_tuple(
        make_tuple(1, 2),
        make_tuple(3, 4, 1),
        5));

    cout << "Mapping indexes to payloads:\n";
    PrintPayloads(payloads, tpl);      

    cout << "\nFinding unused payloads:\n";
    set<int> usedIndexes;
    FindUniqueIndexes(usedIndexes, tpl);
    PrintUnusedPayloads(usedIndexes, payloads);

    cout << "\nMapping to some out of range payloads:\n";
    PrintPayloads(shortPayloads, tpl);      
    
    return 0;
}
Output:
Mapping indexes to payloads:
[[['Payload#1', 'Payload#2'],
['Payload#3', 'Payload#4', 'Payload#1'],
'Payload#5']
]

Finding unused payloads:
Payload#0
Payload#6

Mapping to some out of range payloads:
[[['Payload#1', 'Payload#2'],
['Payload#3', null, 'Payload#1'],
null]
]

Crystal

def with_payload(template, payload, used = nil)
    template.map do |item|
      if item.is_a? Enumerable
        with_payload(item, payload, used)
      else
        used << item
        payload[item]
      end
    end
end

p = {"Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"}
t = { { {1, 2}, {3, 4, 1}, 5}}
used = Set(Int32).new
puts with_payload(t, p, used)

unused = Set(Int32).new((0..6).to_a) - used
puts "Unused indices: #{unused}"
Output:
{{{"Payload#1", "Payload#2"}, {"Payload#3", "Payload#4", "Payload#1"}, "Payload#5"}}
Unused indices: Set{0, 6}

Factor

Words for traversing nested sequences can be found in the sequences.deep vocabulary. Factor's prettyprinter attempts to print structures on a single line (64 characters by default, though this can be changed) if they will fit. Otherwise, the prettyprinter will break them up into multiple lines, preferring to show one member per line if possible. f, Factor's false/nil value, is used to indicate a missing payload.

USING: formatting kernel literals math sequences sequences.deep ;
IN: rosetta-code.nested-template-data

CONSTANT: payloads $[ 7 <iota> [ "Payload#%d" sprintf ] map ]

: insert-payloads ( template -- data-structure )
    [ dup fixnum? [ payloads ?nth ] when ] deep-map ;
    
{ { { 1 2 }
    { 3 4 1 }
    5 } }
    
{ { { 1 2 }
    { 10 4 1 }
    5 } }
    
[ dup insert-payloads "Template: %u\nData Structure: %u\n"
printf ] bi@
Output:
Template: { { { 1 2 } { 3 4 1 } 5 } }
Data Structure: {
    {
        { "Payload#1" "Payload#2" }
        { "Payload#3" "Payload#4" "Payload#1" }
        "Payload#5"
    }
}
Template: { { { 1 2 } { 10 4 1 } 5 } }
Data Structure: {
    {
        { "Payload#1" "Payload#2" }
        { f "Payload#4" "Payload#1" }
        "Payload#5"
    }
}

Go

Go's standard library includes a "text/template" package which can be used for this task.

The integer indices are represented by the keys of a map whose corresponding value is the appropriate payload string. Templates have their own mini-language and, for a map P with key n, the expression:

{{index .P n}}

will be replaced by the corresponding payload.


If an integer index either doesn't exist in the map or maps to an empty payload, then the above expression will simply be replaced by an empty string when the template is executed.

package main

import (
    "fmt"
    "os"
    "sort"
    "strings"
    "text/template"
)

func main() {
    const t = `[[[{{index .P 1}}, {{index .P 2}}],
  [{{index .P 3}}, {{index .P 4}}, {{index .P 1}}], 
  {{index .P 5}}]]
`
    type S struct {
        P map[int]string
    }

    var s S
    s.P = map[int]string{
        0: "'Payload#0'", 1: "'Payload#1'", 2: "'Payload#2'", 3: "'Payload#3'",
        4: "'Payload#4'", 5: "'Payload#5'", 6: "'Payload#6'",
    }
    tmpl := template.Must(template.New("").Parse(t))
    tmpl.Execute(os.Stdout, s)

    var unused []int
    for k, _ := range s.P {
        if !strings.Contains(t, fmt.Sprintf("{{index .P %d}}", k)) {
            unused = append(unused, k)
        }
    }
    sort.Ints(unused)
    fmt.Println("\nThe unused payloads have indices of :", unused)
}
Output:
[[['Payload#1', 'Payload#2'],
  ['Payload#3', 'Payload#4', 'Payload#1'], 
  'Payload#5']]

The unused payloads have indices of : [0 6]

Haskell

The problem is ideal for demonstrating the Functor and Traversable concepts.

Being a functor allows changing the contents of a complex data structure, keeping structure unchanged (via fmap function). This property already matches the template idea, but we can go further. The structure may be foldable as well, allowing aggregation of contents, using arbitrary monoid or aggregating function. Moreover foldable functor may be traversable, giving the ability to modify the complex structure contents with computations held in a given applicative or monadic context. All these properties are well defined, have solid theoretical background and are presented by classes: Functor, Foldable and Traversable.

For wide class of data structures instances of all these classes may be derived by the compiler in a sound unique way. The data template given in the task is exactly the case of a functor.

If we do not bother about neat textual representation, the definition of traversable nested template is as easy as following:

{-# language DeriveTraversable #-}

data Template a = Val a | List [Template a]
  deriving ( Show
           , Functor
           , Foldable
           , Traversable )

Functorial property of a data type is sufficient for defining the universal substitutor of keys/indices by payload data:

subst :: (Functor t, Eq i) => [(i,a)] -> t i -> t (Maybe a)
subst d = fmap (`lookup` d)

It is possible to turn any list of payloads into a map by simple helper function:

indexed :: [a] -> [(Int, a)]
indexed = zip [0..]

Now we can make substitutions to flat lists or nested templates:

t :: Template Int
t = List [ List [Val 1, Val 2]
         , List [Val 3, Val 4, Val 10]
         , Val 5]

payloads :: [(Int, String)]
payloads = [(i, "payload#"++show i) | i <- [0..6]]
λ> subst payloads [6,2,1,2]
[Just "payload#6",Just "payload#2",Just "payload#1",Just "payload#2"]

λ> sequence $ subst payloads [6,2,1,2]
Just ["payload#6","payload#2","payload#1","payload#2"]

λ> indexed "traverse"
[(0,'t'),(1,'r'),(2,'a'),(3,'v'),(4,'e'),(5,'r'),(6,'s'),(7,'e')]

λ> subst (indexed "traverse") [6,7,1,3,4,1]
[Just 's',Just 'e',Just 'r',Just 'v',Just 'e',Just 'r']

λ> sequence . subst (indexed "traverse") [6,7,1,3,4,1]
Just "server"

λ> subst payloads t
List [ List [Val (Just "payload#1"),Val (Just "payload#2")]
     , List [Val (Just "payload#3"),Val (Just "payload#4"),Val Nothing]
     , Val (Just "payload#5")]

λ> sequence $ subst payloads t
Nothing

In the last case not all substitutions could be done, so the whole substitution failed. The sequence function works for any traversable structures.

Foldable properties of templates (with a little help of monoids) allow to implement extended tasks.

unusedIndices :: (Foldable t, Eq i) => [(i,a)] -> t i -> [i]
unusedIndices d = foldMap unused
  where unused i = maybe (pure i) (pure []) $ lookup i d

unusedData :: (Foldable t, Eq i) => [(i, a)] -> t i -> [(i,a)]
unusedData = foldr delete
  where delete i = filter ((i /= ) . fst)
λ> unusedIndices payloads t
[10]

λ> unusedData payloads t
[(0,"payload#0"),(6,"payload#6")]

J

Group substitution

   Substitute=: ({.@:[)`(I.@:(= {:)~)`]}

   NB. aside: demonstrate Substitution
   ] A =: ;/ i. 8
┌─┬─┬─┬─┬─┬─┬─┬─┐
│0│1│2│3│4│5│6│7│
└─┴─┴─┴─┴─┴─┴─┴─┘

   ] B =: ('xxxx' ; 3)
┌────┬─┐
│xxxx│3│
└────┴─┘

   B Substitute A
┌─┬─┬─┬────┬─┬─┬─┬─┐
│0│1│2│xxxx│4│5│6│7│
└─┴─┴─┴────┴─┴─┴─┴─┘

   B Substitute A , < 3
┌─┬─┬─┬────┬─┬─┬─┬─┬────┐
│0│1│2│xxxx│4│5│6│7│xxxx│
└─┴─┴─┴────┴─┴─┴─┴─┴────┘

Convert template to j structured data

   NB. algorithm: evaluate after rewrite as a j sentence
   NB. the result is an actual structured noun.
   NB. because arrays are homogeneous in data type
   NB.  1) data type validity for an operation takes place just once for all the values in the array which is fast
   NB.  2) but a box next to a 5 is invalid.
   NB. hence the payloads must be individually boxed as well.

   ] p =: ('(<''payload#',''')',~":)&>i.7
(<'payload#0')
(<'payload#1')
(<'payload#2')
(<'payload#3')
(<'payload#4')
(<'payload#5')
(<'payload#6')

   NB. though they look scalar the words are vector
   ] t =: ;: CRLF -.~ 0 :0
 [
    [[1, 2],
     [3, 4, 1], 
     5]]
)
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│[│[│[│1│,│2│]│,│[│3│,│4│,│1│]│,│5│]│]│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘


   t =: ,: t                             NB. itemize t, then append successive substitutions
   t =: t , ('(<' ; , '[') Substitute {: t
   t =: t , ( ')' ; , ']') Substitute {: t

   t
┌──┬──┬──┬─┬─┬─┬─┬─┬──┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│[ │[ │[ │1│,│2│]│,│[ │3│,│4│,│1│]│,│5│]│]│
├──┼──┼──┼─┼─┼─┼─┼─┼──┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
│(<│(<│(<│1│,│2│]│,│(<│3│,│4│,│1│]│,│5│]│]│
├──┼──┼──┼─┼─┼─┼─┼─┼──┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
│(<│(<│(<│1│,│2│)│,│(<│3│,│4│,│1│)│,│5│)│)│
└──┴──┴──┴─┴─┴─┴─┴─┴──┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

   NB. finish the substitutions in one fell swoop
   ] SUBSTITUTIONS=: (<"1 p) ,. ,@":&.> i.7
┌──────────────┬─┐
│(<'payload#0')│0│
├──────────────┼─┤
│(<'payload#1')│1│
├──────────────┼─┤
│(<'payload#2')│2│
├──────────────┼─┤
│(<'payload#3')│3│
├──────────────┼─┤
│(<'payload#4')│4│
├──────────────┼─┤
│(<'payload#5')│5│
├──────────────┼─┤
│(<'payload#6')│6│
└──────────────┴─┘

   [ t =: > (] , (Substitute {:))&.>/(<"1 SUBSTITUTIONS) , < t
┌──┬──┬──┬──────────────┬─┬──────────────┬─┬─┬──┬──────────────┬─┬──────────────┬─┬──────────────┬─┬─┬──────────────┬─┬─┐
│[ │[ │[ │1             │,│2             │]│,│[ │3             │,│4             │,│1             │]│,│5             │]│]│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │]│,│(<│3             │,│4             │,│1             │]│,│5             │]│]│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │)│,│(<│3             │,│4             │,│1             │)│,│5             │)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │)│,│(<│3             │,│4             │,│1             │)│,│5             │)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │)│,│(<│3             │,│4             │,│1             │)│,│(<'payload#5')│)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │)│,│(<│3             │,│(<'payload#4')│,│1             │)│,│(<'payload#5')│)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│2             │)│,│(<│(<'payload#3')│,│(<'payload#4')│,│1             │)│,│(<'payload#5')│)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│1             │,│(<'payload#2')│)│,│(<│(<'payload#3')│,│(<'payload#4')│,│1             │)│,│(<'payload#5')│)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│(<'payload#1')│,│(<'payload#2')│)│,│(<│(<'payload#3')│,│(<'payload#4')│,│(<'payload#1')│)│,│(<'payload#5')│)│)│
├──┼──┼──┼──────────────┼─┼──────────────┼─┼─┼──┼──────────────┼─┼──────────────┼─┼──────────────┼─┼─┼──────────────┼─┼─┤
│(<│(<│(<│(<'payload#1')│,│(<'payload#2')│)│,│(<│(<'payload#3')│,│(<'payload#4')│,│(<'payload#1')│)│,│(<'payload#5')│)│)│
└──┴──┴──┴──────────────┴─┴──────────────┴─┴─┴──┴──────────────┴─┴──────────────┴─┴──────────────┴─┴─┴──────────────┴─┴─┘

   ] TASK=: ". ;:inv {: t   NB. task output
┌───────────────────────────────────────────────────────────────────┐
│┌─────────────────────────────────────────────────────────────────┐│
││┌─────────────────────┬───────────────────────────────┬─────────┐││
│││┌─────────┬─────────┐│┌─────────┬─────────┬─────────┐│payload#5│││
││││payload#1│payload#2│││payload#3│payload#4│payload#1││         │││
│││└─────────┴─────────┘│└─────────┴─────────┴─────────┘│         │││
││└─────────────────────┴───────────────────────────────┴─────────┘││
│└─────────────────────────────────────────────────────────────────┘│
└───────────────────────────────────────────────────────────────────┘

Explorations

   L. TASK   NB. level
4

   <S:1 TASK   NB. spread boxing at level 1 
┌─────────────────────┬───────────────────────────────┬─────────┐
│┌─────────┬─────────┐│┌─────────┬─────────┬─────────┐│payload#5│
││payload#1│payload#2│││payload#3│payload#4│payload#1││         │
│└─────────┴─────────┘│└─────────┴─────────┴─────────┘│         │
└─────────────────────┴───────────────────────────────┴─────────┘

   [S:0 TASK   NB. leaves
payload#1
payload#2
payload#3
payload#4
payload#1
payload#5

   (".p) -. <S:0 TASK    NB. unused payloads
┌─────────┬─────────┐
│payload#0│payload#6│
└─────────┴─────────┘

   TASK
┌───────────────────────────────────────────────────────────────────┐
│┌─────────────────────────────────────────────────────────────────┐│
││┌─────────────────────┬───────────────────────────────┬─────────┐││
│││┌─────────┬─────────┐│┌─────────┬─────────┬─────────┐│payload#5│││
││││payload#1│payload#2│││payload#3│payload#4│payload#1││         │││
│││└─────────┴─────────┘│└─────────┴─────────┴─────────┘│         │││
││└─────────────────────┴───────────────────────────────┴─────────┘││
│└─────────────────────────────────────────────────────────────────┘│
└───────────────────────────────────────────────────────────────────┘

   {:: TASK   NB. map
┌─────────────────────────────────────────────────────┐
│┌───────────────────────────────────────────────────┐│
││┌─────────────────┬─────────────────────────┬─────┐││
│││┌───────┬───────┐│┌───────┬───────┬───────┐│┌┬┬─┐│││
││││┌┬┬─┬─┐│┌┬┬─┬─┐│││┌┬┬─┬─┐│┌┬┬─┬─┐│┌┬┬─┬─┐│││││2││││
│││││││0│0│││││0│1│││││││1│0│││││1│1│││││1│2│││└┴┴─┘│││
││││└┴┴─┴─┘│└┴┴─┴─┘│││└┴┴─┴─┘│└┴┴─┴─┘│└┴┴─┴─┘││     │││
│││└───────┴───────┘│└───────┴───────┴───────┘│     │││
││└─────────────────┴─────────────────────────┴─────┘││
│└───────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────┘

   (0; 0; 0; 0) {:: TASK    NB. indexing
payload#1

   (0;0;2){::TASK
payload#5

Gerund representation

   NB. finally, look at the representation of the substitution gerund
   ({.@:[)`(I.@:(= {:)~)`]
┌───────────┬──────────────────────────┬─┐
│┌──┬──────┐│┌─┬──────────────────────┐│]│
││@:│┌──┬─┐│││~│┌────────────────────┐││ │
││  ││{.│[││││ ││┌──┬───────────────┐│││ │
││  │└──┴─┘│││ │││@:│┌──┬──────────┐││││ │
│└──┴──────┘││ │││  ││I.│┌─┬──────┐│││││ │
│           ││ │││  ││  ││2│┌─┬──┐││││││ │
│           ││ │││  ││  ││ ││=│{:│││││││ │
│           ││ │││  ││  ││ │└─┴──┘││││││ │
│           ││ │││  ││  │└─┴──────┘│││││ │
│           ││ │││  │└──┴──────────┘││││ │
│           ││ ││└──┴───────────────┘│││ │
│           ││ │└────────────────────┘││ │
│           │└─┴──────────────────────┘│ │
└───────────┴──────────────────────────┴─┘

jq

In this entry, we suppose that both the template and the payload are provided externally, both because that is normally how programs of the type under consideration are used, and because it is consistent with a "separation of concerns" principle. To keep things simple, let's put everything into a bash script.

For the main task, the key ideas here are (1) to use a JSON dictionary to store the integer-to-payload mapping; and (2) to use the built-in filter, `walk/1`, to instantiate the template.

#!/bin/bash
function template {
  cat<<EOF
  [
    [[1, 2],
     [3, 4, 1], 
      5 ]]
EOF
}

function payload {
  for i in $(seq 0 6) ; do
    echo Payload#$i
  done
}

# Task 1: Template instantiation
payload | jq -Rn --argfile t <(template) '
  ([inputs] | with_entries(.key |= tostring)) as $dict
  | $t
  | walk(if type == "number" then $dict[tostring] else . end)
'

This produces the expected output, as also shown below.

For the second task, we could separately invoke jq similarly:

payload | jq -Rn --argfile t <(template) '
  ([inputs] | with_entries(.key |= tostring)) as $dict
  | $dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
'

Or, if you prefer one invocation of jq for both tasks:

payload | jq -Rrn --argfile t <(template) '
  ([inputs] | with_entries(.key |= tostring)) as $dict
  | $t 
  | walk(if type == "number" then $dict[tostring] else . end),
    "\nUnused payload",
    $dict[(($dict|keys_unsorted) - ([ $t | .. | numbers ] | unique | map(tostring) ))[]]
'
Output:
[
  [
    [
      "Payload#1",
      "Payload#2"
    ],
    [
      "Payload#3",
      "Payload#4",
      "Payload#1"
    ],
    "Payload#5"
  ]
]

Unused payload
Payload#0
Payload#6

Julia

The array structure needs to be specified as Any type of data, to allow assignment of String to positions in the array originally containing integers.

t = ([Any[Any[1, 2],
          Any[3, 4, 1],
          5]])

p = ["Payload#$x" for x in 0:6]

for (i, e) in enumerate(t)
    if e isa Number
        t[i] = p[e + 1]
    else
        for (j, f) in enumerate(e)
            if f isa Number
                e[j] = p[f + 1]
            else
                for (k, g) in enumerate(f)
                    if g isa Number
                        f[k] = p[g + 1]
                    end
                end
            end
        end
    end
end


show(t)
Output:

Array{Any,1}[[Any["Payload#1", "Payload#2"], Any["Payload#3", "Payload#4", "Payload#1"], "Payload#5"]]

Mathematica/Wolfram Language

t = ToExpression[StringReplace["[[[1,2],[3,4,1],5]]", {"[" -> "{", "]" -> "}"}]];
p = "Payload#" <> ToString[#] & /@ Range[6];
Map[p[[#]] &, t, {-1}]
Output:
{{{"Payload#1", "Payload#2"}, {"Payload#3", "Payload#4", "Payload#1"}, "Payload#5"}}


M2000 Interpreter

Font "Courier New"
cls
Module Checkit {
      t=(((1,2), (3,4,1),5),)    ' use (1,) for one item tuple
      Tuple$ = lambda$ (a, feed$=" ") -> {
            \\ we can pass a tuple of two arguments or two arguments
            k=each(a)
            lim=len(a)-1
            res$="("
            link a to a() ' to use type$()
            while k {
                  if type$(a(k^))="mArray" then
                        res$+=Lambda$(array(a, k^),feed$+" ")
                        if k^<lim then
                              res$+={,
                              }+feed$
                        end if
                  else      
                        res$+= trim$(str$(array(k)))
                        if k^<lim then res$+=", "
                  end if
            }
            =res$+")"
      }
      TotalPayload = lambda (a)->{
            k=each(a)
            link a to a()
            res=0
            while k {
                  if type$(a(k^))="mArray" then
                        res+=Lambda(a(k^))
                  else
                        res++
                  end if
            }
            =res
      }
      Payload = lambda (a,payloads as list)->{
           misspayloads=List
           used=list
           inner=lambda misspayloads, p=1, payloads, used (a)-> {
                  k=each(a)
                  res=(,)
                  link a to a()
                  while k {
                        if type$(a(k^))="mArray" then
                             Append res, (Lambda(a(k^)),)
                        else
                              curpayload$="Payload#"+trim$(str$(array(k)))

                              if not exist(payloads, curpayload$) Then
                                    if not exist(used, curpayload$) Then
                                          Append res, ("missing#pos"+trim$(str$(p)),)
                                          append misspayloads, p:=curpayload$
                                    else                               
                                          Append res, (curpayload$,)
                                    End if
                                    p++
                              else
                                    Append res, (curpayload$,)
                                    if exist(payloads, curpayload$) then 
                                          delete payloads, curpayload$
                                          if not exist(used, curpayload$) then append used, curpayload$
                                    end if
                                    p++
                              end if
                        end if
                  }
                  =res
            }
            =inner(a), payloads, misspayloads
      }
      Expand$ =lambda$ (a as array, unused as list, misspayloads as list)-> {
            Read ? space$
            inner$= lambda$ (a, feed$=" ")->{
                  k=each(a)
                  lim=len(a)-1
                  res$="["
                  link a to a() ' to use type$()
                  while k {
                        if type$(a(k^))="mArray" then
                              res$+=Lambda$(array(a, k^),feed$+" ")
                              if k^<lim then
                                    res$+={,
                                    }+feed$
                              end if
                        else      
                              res$+= "'"+array$(k)+"'"
                              if k^<lim then res$+=", "
                        end if
                  }
                  =res$+"]"      
            }
            document unused$="Unused Payloads"+{
            }
            if len(unused)>0 then
                  un=each(unused)
                  while un {
                        unused$="  "+eval$(un)+{
                        }
                  }
            else
                  unused$="  -"
            end if
            if len(misspayloads)>0 then
                  un=each(misspayloads)
                  lim=len(misspayloads)-1
                  document missing$="Missing in position: "+{
                  }
                  while un {
                        missing$="  "+eval$(un)+"-pos"+eval$(un,un^)+{
                        }
                  }
                  =inner$(a, space$)+{
                  }+unused$+missing$
            Else
                  =inner$(a, space$)+{
                  } + unused$
            End if
      }
      flush
      Data t, (((1,10), (3,4,16),5),)
      While not empty {
            Read t
            Document result$="Payloads:"+{
            }
            p=list
            for i=0 to 6 {
                  Append p, "Payload#"+trim$(str$(i))
                  result$="  "+eval$(p, i)+{
                  }
            }
            result$="Template:"+{
            }
            result$="  "+Tuple$(t, "   ")+{
            }
            result$="Template with Payloads:"+{
            }
            m=Payload(t, p)
            result$="  "+Expand$(!m, "   ")
            
            clipboard result$
      }
      
}
Checkit
Report clipboard$
Output:
Payloads:
  Payload#0
  Payload#1
  Payload#2
  Payload#3
  Payload#4
  Payload#5
  Payload#6
Template:
  (((1, 2),
    (3, 4, 1),
    5))
Template with Payloads:
  [[['Payload#1', 'Payload#2'],
    ['Payload#3', 'Payload#4', 'Payload#1'],
    'Payload#5']]
Unused Payloads
  Payload#0
  Payload#6
Payloads:
  Payload#0
  Payload#1
  Payload#2
  Payload#3
  Payload#4
  Payload#5
  Payload#6
Template:
  (((1, 10),
    (3, 4, 16),
    5))
Template with Payloads:
  [[['Payload#1', 'missing#pos2'],
    ['Payload#3', 'Payload#4', 'missing#pos5'],
    'Payload#5']]
Unused Payloads
  Payload#0
  Payload#6
  Payload#2
Missing in position: 
  Payload#10-pos2
  Payload#16-pos5

Nim

import macros,sugar,strformat
#macro to take a nested tuple and return a type
#e.g. (int,(int,int))=>(string,(string,string))
proc intstr(n: NimNode): NimNode =
  if n.kind == nnkSym:
    return ident("string")
  result = nnkPar.newNimNode()
  for i in 1..<n.len:
    result.add(intstr(n[i]))

macro tuptype(t: typed): untyped = intstr(t.getType)


proc replace(t: tuple | int, p: openArray[string]): auto =
  when t is int: (if t in 0..<p.len: p[t] else: "nil")
  else:
    var res: tuptype(t)
    for k, v in t.fieldpairs:
      #k will be 'Field0', so we convert to an integer index
      res[k[^1].int - '0'.int] = replace(v, p)
    return res
when isMainModule:
  let p = collect(for i in 0..5: &"payload{i}")

  let tplt1 = ((1,2),(3,4,1),5)
  let tplt2 = ((1,2),(3,4,1),6)
  echo replace(tplt1, p)
  echo replace(tplt2, p)
Output:
(("payload1", "payload2"), ("payload3", "payload4", "payload1"), "payload5")
(("payload1", "payload2"), ("payload3", "payload4", "payload1"), "nil")

Perl

Only handles nesting one level deep. Missing data is undef in the data structure, an empty string in the pretty-printer.

sub fulfill {
    my   @payloads;
    push @payloads, 'Payload#' . $_ for 0..5;
    my      @result;
    push    @result, ref $_ eq 'ARRAY' ? [@payloads[@$_]] : @payloads[$_] for @{@_[0]};
    return [@result];
}

sub formatted {
    my $result;
    $result .= ref $_ eq 'ARRAY' ? '[ "'. join('", "', @$_) . '" ], ' : qq{"$_"} for @{@_[0]};
    return '[ ' . $result . " ]\n";
}

print formatted fulfill( [[1,2], [ 3,4,1], 5] );
print formatted fulfill( [[1,2], [10,4,1], 5] );
Output:
[ [ "Payload#1", "Payload#2" ], [ "Payload#3", "Payload#4", "Payload#1" ], "Payload#5" ]
[ [ "Payload#1", "Payload#2" ], [ "", "Payload#4", "Payload#1" ], "Payload#5" ]

Arbitrary Nesting

#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Nested_templated_data
use warnings;
use Data::Dump 'dd';

my $t = [
    [[1, 2],
     [3, 4, 1], 
     5]];
 
my $p = [ map "Payload#$_", 0 .. 6 ];
dd { 'template' => $t, 'payload' => $p };

my $output = filltemplate( $t, $p );
dd { 'output' => $output };

sub filltemplate
  {
  my ($t, $p) = @_;
  return ref $t eq 'ARRAY' ? [ map filltemplate($_, $p), @$t ] : $p->[$t];
  }
Output:
{
  payload  => [
                "Payload#0",
                "Payload#1",
                "Payload#2",
                "Payload#3",
                "Payload#4",
                "Payload#5",
                "Payload#6",
              ],
  template => [[[1, 2], [3, 4, 1], 5]],
}
{
  output => [
    [
      ["Payload#1", "Payload#2"],
      ["Payload#3", "Payload#4", "Payload#1"],
      "Payload#5",
    ],
  ],
}

Phix

This task almost feels custom-built for Phix.

Note that Phix indexes are normally 1-based, but to better match the task description those in the templates are 0-based

constant template = { { { 1, 2 }, { 3, 4, 1, }, 5 } },
         template2 =  { { { 1, 2 }, { 10, 4, 1 }, 5 } },
         payload = {"Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"}
sequence unused = repeat(true,length(payload)),
         missing = {}
 
function fill(object t, sequence p)
    if integer(t) then
        if t>=length(p) then
            if not find(t,missing) then missing &= t end if
            return sprintf("*** index error (%d>%d) ***",{t,length(p)-1})
        end if
        unused[t+1] = false
        return p[t+1]
    end if
    for i=1 to length(t) do
        t[i] = fill(t[i],p)
    end for
    return t
end function
 
ppOpt({pp_Nest,2})
pp(fill(template,payload))
pp(fill(template2,payload))
 
sequence idx = {}
for i=1 to length(unused) do
    if unused[i] then idx &= i-1 end if
end for
printf(1,"\nThe unused payloads have indices of :%s\n", {sprint(idx)})
 
if length(missing) then
    printf(1,"Missing payloads: %s\n", {sprint(missing)})
end if
{{{"Payload#1", "Payload#2"},
  {"Payload#3", "Payload#4", "Payload#1"},
  "Payload#5"}}
{{{"Payload#1", "Payload#2"},
  {"*** index error (10>6) ***", "Payload#4", "Payload#1"},
  "Payload#5"}}

The unused payloads have indices of :{0,6}
Missing payloads: {10}

Python

This uses f-strings from Python3.6+.

I choose to use nested tuples for the template structure, and a dict to map integer indices to corresponding payload strings.

A distinctive string is used to indicate missing payloads.

from pprint import pprint as pp

class Template():
    def __init__(self, structure):
        self.structure = structure
        self.used_payloads, self.missed_payloads = [], []
    
    def inject_payload(self, id2data):
        
        def _inject_payload(substruct, i2d, used, missed):
            used.extend(i2d[x] for x in substruct if type(x) is not tuple and x in i2d)
            missed.extend(f'??#{x}' 
                          for x in substruct if type(x) is not tuple and x not in i2d)
            return tuple(_inject_payload(x, i2d, used, missed) 
                           if type(x) is tuple 
                           else i2d.get(x, f'??#{x}') 
                         for x in substruct)
                           
        ans = _inject_payload(self.structure, id2data, 
                              self.used_payloads, self.missed_payloads)
        self.unused_payloads = sorted(set(id2data.values()) 
                                      - set(self.used_payloads))
        self.missed_payloads = sorted(set(self.missed_payloads))
        return ans

if __name__ == '__main__':
    index2data = {p: f'Payload#{p}' for p in range(7)}
    print("##PAYLOADS:\n  ", end='')
    print('\n  '.join(list(index2data.values())))
    for structure in [
     (((1, 2),
       (3, 4, 1),
       5),),
    
     (((1, 2),
       (10, 4, 1),
       5),)]:
        print("\n\n# TEMPLATE:")
        pp(structure, width=13)
        print("\n TEMPLATE WITH PAYLOADS:")
        t = Template(structure)
        out = t.inject_payload(index2data)
        pp(out)
        print("\n UNUSED PAYLOADS:\n  ", end='')
        unused = t.unused_payloads
        print('\n  '.join(unused) if unused else '-')
        print(" MISSING PAYLOADS:\n  ", end='')
        missed = t.missed_payloads
        print('\n  '.join(missed) if missed else '-')
Output:
##PAYLOADS:
  Payload#0
  Payload#1
  Payload#2
  Payload#3
  Payload#4
  Payload#5
  Payload#6


# TEMPLATE:
(((1, 2),
  (3, 4, 1),
  5),)

 TEMPLATE WITH PAYLOADS:
((('Payload#1', 'Payload#2'),
  ('Payload#3', 'Payload#4', 'Payload#1'),
  'Payload#5'),)

 UNUSED PAYLOADS:
  Payload#0
  Payload#6
 MISSING PAYLOADS:
  -


# TEMPLATE:
(((1, 2),
  (10, 4, 1),
  5),)

 TEMPLATE WITH PAYLOADS:
((('Payload#1', 'Payload#2'),
  ('??#10', 'Payload#4', 'Payload#1'),
  'Payload#5'),)

 UNUSED PAYLOADS:
  Payload#0
  Payload#3
  Payload#6
 MISSING PAYLOADS:
  ??#10

R

This is a fairly straightforward implementation in R using a recursive function. It's not likely the most efficient in the world.

fill_template <- function(x, template, prefix = "Payload#") {
  for (i in seq_along(template)) {
    temp_slice <- template[[i]]
    if (is.list(temp_slice)) {
      template[[i]] <- fill_template(x, temp_slice, prefix)
    } else {
      temp_slice <- paste0(prefix, temp_slice)
      template[[i]] <- x[match(temp_slice, x)]
    }
  }
  return(template)
}

library("jsonlite") # for printing the template and result
template <- list(list(c(1, 2), c(3, 4), 5))
payload  <- paste0("Payload#", 0:6)
result   <- fill_template(payload, template)

cat(sprintf(
  "Template\t%s\nPayload\t%s\nResult\t%s", 
  toJSON(template, auto_unbox = TRUE),
  toJSON(payload, auto_unbox = TRUE),
  toJSON(result, auto_unbox = TRUE)
))
Output:
Template [[[1,2],[3,4],5]]
Payload  ["Payload#0","Payload#1","Payload#2","Payload#3","Payload#4","Payload#5","Payload#6"]
Result   [[["Payload#1","Payload#2"],["Payload#3","Payload#4"],"Payload#5"]]


Racket

rackunit is used to test the outcomes of template application. So no output indicates expectations met (i.e. success).

#lang racket

(define current-not-found-handler
  (make-parameter (λ (idx max) (raise-range-error 'substitute-template "integer?" "" idx 0 max))))

(define ((substitute-template template) payloads)
  (define match-function
    (match-lambda
      [(? nonnegative-integer? idx) #:when (< idx (length payloads)) (list-ref payloads idx)]
      [(? nonnegative-integer? idx) ((current-not-found-handler) idx (sub1 (length payloads)))]
      [(list (app match-function substitutions) ...) substitutions]))
  (match-function template))

(module+ test
  (require rackunit)

  (define substitute-in-t (substitute-template '(((1 2)
                                                  (3 4 1)
                                                  5))))
 
  (define p '(Payload#0 Payload#1 Payload#2 Payload#3 Payload#4 Payload#5 Payload#6))

  (check-equal? (substitute-in-t p)
                '(((Payload#1 Payload#2)
                   (Payload#3 Payload#4 Payload#1)
                   Payload#5)))

  (define out-of-bounds-generating-template-substitution (substitute-template '(7)))
  
  (check-exn exn:fail:contract? (λ () (out-of-bounds-generating-template-substitution p)))

  (parameterize ((current-not-found-handler (λ (idx max) (format "?~a" idx))))
    (check-equal? (out-of-bounds-generating-template-substitution p) '("?7"))))

Raku

(formerly Perl 6)

Works with: Rakudo version 2020.08.1

Explicitly not using strings, using one data structure to fill in another. Since it isn't a string, the output format removes the newlines from the template; line feed (white space in general) isn't particularly significant in Raku data structures. It does preserve the nesting though. In the second example, payload "buckets" that don't exist result in an undefined value being inserted; by default: Any.

say join "\n  ", '##PAYLOADS:', |my @payloads = 'Payload#' X~ ^7;

for [
     (((1, 2),
       (3, 4, 1),
       5),),

     (((1, 2),
       (10, 4, 1),
       5),)
    ] {
    say "\n      Template: ", $_.raku;
    say "Data structure: { @payloads[|$_].raku }";
}
Output:
##PAYLOADS:
  Payload#0
  Payload#1
  Payload#2
  Payload#3
  Payload#4
  Payload#5
  Payload#6

      Template: $(((1, 2), (3, 4, 1), 5),)
Data structure: ((("Payload#1", "Payload#2"), ("Payload#3", "Payload#4", "Payload#1"), "Payload#5"),)

      Template: $(((1, 2), (10, 4, 1), 5),)
Data structure: ((("Payload#1", "Payload#2"), (Any, "Payload#4", "Payload#1"), "Payload#5"),)

REXX

version 1

/* REXX */
tok.=''
Do i=0 To 6
  tok.i="'Payload#"i"'"
  End
t1='[[[1,2],[3,4,1],5]]'
t2='[[[1,6],[3,4,7,0],5]]'
Call transform t1
Call transform t2
Exit

transform:
Parse Arg t 1 tt
/* http://rosettacode.org/wiki/Nested_templated_data */
/*
[[['Payload#1', 'Payload#2'],
  ['Payload#3', 'Payload#4', 'Payload#1'],
  'Payload#5']]
*/
lvl=0
n.=0
o=''
w=''
used.=0
Do While t<>''
  Parse Var t c +1 1 c3 +3 1 c2 +2
  u=' '
  v=' '
  Select
    When c3='],[' Then Do
      o=o'  '
      w=w'  '
      t=substr(t,3)
      End
    When c2='],' Then Do
      o=o' '
      w=w' '
      t=substr(t,2)
      lvl=lvl-1
      End
    When c='[' Then
      lvl=lvl+1
    When c=']' Then
      lvl=lvl-1
    When c=',' Then
      Nop
    Otherwise Do
      u=lvl
      v=c
      End
    End
  t=substr(t,2)
  o=o||u
  w=w||v
  End
Say 'Template' tt
Do i=1 By 1 While w<>''
  If i=1 Then Do
    w=substr(w,4)
    p=pos('  ',w)
    Call o '[[['cont(left(w,p-1))'],'
    w=substr(w,p)
    End
  Else Do
    If left(w,3)='' Then Do
      w=substr(w,4)
      p=pos('  ',w)
      Call o '  ['cont(left(w,p-1))'],'
      w=substr(w,p)
      End
    Else Do
      w=substr(w,3)
      p=pos('  ',w)
      Call o '  'cont(left(w,p-1))']]'
      w=substr(w,p)
      End
    End
  End
Do i=0 To 6
  If used.i=0 Then Say 'Payload' i 'not used'
  End
Call o ' '
Return

o: Say arg(1)
   Return

cont: Procedure Expose tok. used.
  Parse Arg list
  res=''
  Do while list>''
    Parse Var list i list
    res= res tok(i)','
    End
  res=strip(res)
  res=strip(res,'T',',')
  Return res

tok: Procedure Expose tok. used.
Parse Arg i
If tok.i<>'' Then Do
  used.i=1
  Return tok.i
  End
Else
  Return "'Payload#" i "not defined'"
Output:
Template [[[1,2],[3,4,1],5]]
[[['Payload#1', 'Payload#2'],
  ['Payload#3', 'Payload#4', 'Payload#1'],
  'Payload#5']]
Payload 0 not used
Payload 6 not used

Template [[[1,6],[3,4,7,0],5]]
[[['Payload#1', 'Payload#6'],
  ['Payload#3', 'Payload#4', 'Payload# 7 not defined', 'Payload#0'],
  'Payload#5']]
Payload 2 not used

version 2

/* REXX */
tok.=''
Do i=0 To 6
  tok.i="'Payload#"i"'"
  End
t1='[[[1,2],[ 3,4,1],5]]'
t2='1[[[1,6]],[[3,4[7] 0],5]3]9 [8] 9'
Call transform t1
Call transform t2
Exit

transform:
Parse Arg t 1 tt
t=space(t,0)
lvl=0
t.=0
used.=0
undefined=''
Do While t<>''
  Parse Var t c +1 t
  Select
    When c='[' Then
      lvl=lvl+1
    When c=']' Then
      lvl=lvl-1
    When c=',' Then
      Nop
    Otherwise Do
      t=c||t
      p1=pos(']',t)
      p2=pos('[',t)
      Select
        When p2=0 Then p=p1
        When p1=0 Then p=p2
        Otherwise p=min(p1,p2)
        End
      If p=0 Then Do
        Call mem lvl': >'t'<'
        t=''
        End
      Else Do
        Call mem lvl': >'left(t,p-1)'<'
        t=substr(t,p)
        End
      End
    End
  End
Call show
Return

mem:
z=t.0+1
t.z=arg(1)
t.0=z
Return

show:
Say tt
Say 'lvl Element'
Do i=1 To t.0
  Parse Var t.i lvl ':' '>' cont '<'
  ol=right(lvl,3) copies(' ',lvl*3)cont(cont)
  Say ol
  End
Do i=0 To 6
  If used.i=0 Then Say 'Payload' i 'not used'
  End
Do While undefined>''
  Parse Var undefined i undefined
  Say 'Payload' i 'is not defined'
  End
Call o ' '
Return

cont: Procedure Expose tok. used. undefined
  Parse Arg list
  list=translate(list,' ',',')
  res=''
  Do while list>''
    Parse Var list i list
    res= res tok(i)','
    End
  res=strip(res)
  res=strip(res,'T',',')
  Return res

tok: Procedure Expose tok. used. undefined
Parse Arg i
If tok.i<>'' Then Do
  used.i=1
  Return tok.i
  End
Else Do
  If wordpos(i,undefined)=0 Then
    undefined=undefined i
  Return "'Payload#"i "not defined'"
  End

o: Say arg(1)
   Return
Output:
[[[1,2],[ 3,4,1],5]]
lvl Element
  3          'Payload#1', 'Payload#2'
  3          'Payload#3', 'Payload#4', 'Payload#1'
  2       'Payload#5'
Payload 0 not used
Payload 6 not used

1[[[1,6]],[[3,4[7] 0],5]3]9 [8] 9
lvl Element
  0 'Payload#1'
  3          'Payload#1', 'Payload#6'
  3          'Payload#3', 'Payload#4'
  4             'Payload#7 not defined'
  3          'Payload#0'
  2       'Payload#5'
  1    'Payload#3'
  0 'Payload#9 not defined'
  1    'Payload#8 not defined'
  0 'Payload#9 not defined'
Payload 2 not used
Payload 7 is not defined
Payload 9 is not defined
Payload 8 is not defined

VBA

VBA allows arrays of variant, so the elements of an array can be both scalars as arrays of different sizes.

Public Sub test()
    Dim t(2) As Variant
    t(0) = [{1,2}]
    t(1) = [{3,4,1}]
    t(2) = 5
    p = [{"Payload#0","Payload#1","Payload#2","Payload#3","Payload#4","Payload#5","Payload#6"}]
    Dim q(6) As Boolean
    For i = LBound(t) To UBound(t)
        If IsArray(t(i)) Then
            For j = LBound(t(i)) To UBound(t(i))
                q(t(i)(j)) = True
                t(i)(j) = p(t(i)(j) + 1)
            Next j
        Else
            q(t(i)) = True
            t(i) = p(t(i) + 1)
        End If
    Next i
    For i = LBound(t) To UBound(t)
        If IsArray(t(i)) Then
            Debug.Print Join(t(i), ", ")
        Else
            Debug.Print t(i)
        End If
    Next i
    For i = LBound(q) To UBound(q)
        If Not q(i) Then Debug.Print p(i + 1); " is not used"
    Next i
End Sub
Output:
Payload#1, Payload#2
Payload#3, Payload#4, Payload#1
Payload#5
Payload#0 is not used
Payload#6 is not used

Wren

Translation of: Crystal
Library: Wren-set
Library: Wren-sort
import "/set" for Set
import "/sort" for Sort

var withPayload // recursive function 
withPayload = Fn.new { |template, payload, used|
    return template.map { |item|
        if (item is List) {
            return withPayload.call(item, payload, used)
        } else {
            used.add(item)
            return "'%(payload[item])'"
        }
    }.toList
}

var p = ["Payload#0", "Payload#1", "Payload#2", "Payload#3", "Payload#4", "Payload#5", "Payload#6"]
var t = [[[1, 2], [3, 4, 1], 5]]
var used = []
System.print(withPayload.call(t, p, used))
System.print()
var unused  = Set.new(0..6).except(Set.new(used)).toList
Sort.insertion(unused)
System.print("The unused payloads have indices of %(unused).")
Output:
[[['Payload#1', 'Payload#2'], ['Payload#3', 'Payload#4', 'Payload#1'], 'Payload#5']]

The unused payloads have indices of [0, 6].


zkl

Formatting is lost as zkl is format free. A pretty printer could be written but the tasks asks for a data structure.

Void is used as a marker for an unknown payload.

var payloads=[1..6].pump(List,"Payload#".append);

fcn get(n){ try{ payloads[n - 1] }catch{ Void } }
fcn sub(list){ list.pump(List, fcn(n){ if(n.isType(List)) sub(n) else get(n) }) }
foreach p in (T( 
     T(T(T(1, 2),
         T(3, 4, 1),
         5),),
   T(T(T(1, 2),
       T(10,4, 1),
         5),))){
   println("      Template: %s\nData structure: %s".fmt(p,sub(p)));
}
Output:
      Template: L(L(L(1,2),L(3,4,1),5))
Data structure: L(L(L("Payload#1","Payload#2"),L("Payload#3","Payload#4","Payload#1"),"Payload#5"))
      Template: L(L(L(1,2),L(10,4,1),5))
Data structure: L(L(L("Payload#1","Payload#2"),L(Void,"Payload#4","Payload#1"),"Payload#5"))