Stream: mapping-framework
Topic: tutorial step 14
Harrison Tarr (Jan 09 2020 at 19:33):
hi all, i've been playing with the FHIR mapping language (big thanks to @Oliver Egger and @David Hay for their help) and ive quickly found myself in a tricky situation.
i have two input lists that i'd like to map into one input list
essentially:
{a, b, c} + {1, 2, 3} -> {a1, b2, c3}
from the description of tutorial step 14 (https://www.hl7.org/fhir/mapping-tutorial.html), i think that should be covered there, but it's marked as to do. does anyone have an example of what the map rules should look like to iterate through two lists simultaneously and accomplish this?
Oliver Egger (Jan 10 2020 at 13:29):
@Harrison Tarr challenging task!
I came up the following for the first element element of the list:
map "http://hl7.org/fhir/StructureMap/unioncollection" = "unioncollection" uses "http://hl7.org/fhir/StructureDefinition/tutorial-left" alias TLeft as source uses "http://hl7.org/fhir/StructureDefinition/tutorial-right" alias TRight as target group combine(source source : TLeft, target target : TRight) { source.a first as a -> target.c = (%source.a[0]+%source.b[0]) "concatenated"; // source.a as a -> target.c as c, c = (%source.a.item($index) + %source.b.item($index)) "concatenate"; }
to run above i need to update the pull request but no idea how you either a) propagate the index of the list into the target or b) do a recursion of the tail of the two collections. if instead of the target a variable could be assigned in the target which could be reused, then it would be feasable. any other approaches @Grahame Grieve @Vadim Peretokin @Alexander Zautke ?
Alexander Zautke (Jan 12 2020 at 22:10):
The rule that for merging the two values should be evaluated by the engine once for every element. Therefore you should not need to have any kind of indices.
Alexander Zautke (Jan 12 2020 at 22:10):
map "http://hl7.org/fhir/StructureMap/unioncollection" = "unioncollection" uses "http://hl7.org/fhir/StructureDefinition/tutorial-left" alias TLeft as source uses "http://hl7.org/fhir/StructureDefinition/tutorial-right" alias TRight as target group combine(source test : TLeft, target combined : TRight) { test.a as a, test.b as b -> combined.c = evaluate(test, '%a + %b') collate; }
Alexander Zautke (Jan 12 2020 at 22:13):
%a and %b should capture the current value for each iteration and collate should re-use the target.
Oliver Egger (Jan 13 2020 at 07:21):
according to the spec this would give a1, a2, a3, b1, b2, b3, c1, c2, c3 and not a1, b2, c3 ?
If there are multiple source statements, the rule applies for the permutation of the source elements from each source statement. E.g. if there are 2 source statements, each with 2 matching elements, the rule applies 4 times, one for each combination.
Alexander Zautke (Jan 13 2020 at 15:42):
Mhm, right...
Alexander Zautke (Jan 13 2020 at 15:43):
What would be if you nest the second element selection?
Alexander Zautke (Jan 13 2020 at 15:44):
Nevermind, same result...
Alexander Zautke (Jan 13 2020 at 17:35):
Our the .NET implementation doesn’t currently support the external variables in the FHIRPath statement. That’s why I can’t test the statement. I‘m a bit out of ideas
Brian Postlethwaite (Jan 13 2020 at 22:44):
Are you sure on that?
You just need to add them to the symbol table being used by the fhirpath engine (only supports string types at this stage though)
For my usage, I provide a new Symbol table with the vars, that wraps the core symbol table and pass that to the execution engine.
Alexander Zautke (Jan 13 2020 at 22:54):
Yes, the mapping engine uses internally already a parser based on Superpower for everything except FHIRPath. Therefore we have separate contexts between the selection of the source and the evaluation function (parsed and executed by the Sprache parser / API FHIRPath compiler). There is no shared symbol table between these two worlds. We have a solution to make it work for where statements but not for the evaluation function.
Brian Postlethwaite (Jan 14 2020 at 01:43):
Ok
Alexander Zautke (Jan 15 2020 at 09:56):
group combine(source source : TLeft, target target : TRight) {
let tailA = (%source.a.tail())
let tailB = (%source.b.tail())
source.a first as a -> target.c = (%source.a[0]+%source.b[0]) "concatenated" then combine(tailA, tailB);
}
Alexander Zautke (Jan 15 2020 at 09:56):
@Oliver Egger and I came up with a solution using let statements (See J#21642)
Last updated: Apr 12 2022 at 19:14 UTC