Nested templated data: Difference between revisions
Thundergnat (talk | contribs) →{{header|Perl 6}}: More concisely |
→{{header|Factor}}: Generate payloads instead of hard-coding them. |
||
Line 39: | Line 39: | ||
=={{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 |
<lang factor>USING: formatting kernel literals math sequences sequences.deep ; |
||
IN: rosetta-code.nested-template-data |
IN: rosetta-code.nested-template-data |
||
CONSTANT: payloads |
CONSTANT: payloads $[ 7 <iota> [ "Payload#%d" sprintf ] map ] |
||
Payload#0 |
|||
Payload#1 |
|||
Payload#2 |
|||
Payload#3 |
|||
Payload#4 |
|||
Payload#5 |
|||
Payload#6 |
|||
} |
|||
: insert-payloads ( template -- data-structure ) |
: insert-payloads ( template -- data-structure ) |
||
Line 63: | Line 55: | ||
5 } } |
5 } } |
||
⚫ | |||
[ |
|||
⚫ | |||
⚫ | |||
printf |
|||
⚫ | |||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
Revision as of 01:33, 20 June 2018
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 b avoided. The idea is to use the native, or usual implementation of lists/tuples etc of the language and to hierarchically traverse the template/generate the output.
- Task Detail
Given the following input template t
and list of payloads p
:
<lang># 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'</lang>
The correct output should have the following structure, (although spacing and linefeeds may differ, the nesting and order should follow): <lang>[[['Payload#1', 'Payload#2'],
['Payload#3', 'Payload#4', 'Payload#1'], 'Payload#5']]</lang>
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.
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.
<lang factor>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@</lang>
- 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" } }
Perl 6
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 Perl 6 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;
for [
(((1, 2), (3, 4, 1), 5),),
(((1, 2), (10, 4, 1), 5),) ] { say "\n Template: ", $_.perl; say "Data structure: { @payloads[|$_].perl }";
}</lang>
- 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"),)
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. <lang python>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 '-')</lang>
- 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
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. <lang zkl>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) }) }</lang> <lang zkl>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)));
}</lang>
- 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"))