Sure, thanks for taking a look!
Syntax:
Transform(template, separator, List)The goal is to transform each element of a list using a given pattern, returning a new list with the same size where each element is transformed.
For instance, this expression can be used to process the [Actors] field to get a series of <img> tags pointing to the Actor profile PNGs (to show Actor pics in theater/thumbnail view):
<img src="E:\JRiver\Actors\Left(listitem([Actors],0), 1)\listitem([Actors],0).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],1), 1)\listitem([Actors],1).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],2), 1)\listitem([Actors],2).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],3), 1)\listitem([Actors],3).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],4), 1)\listitem([Actors],4).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],5), 1)\listitem([Actors],5).png" width="130"> <img src="E:\JRiver\Actors\Left(listitem([Actors],6), 1)\listitem([Actors],6).png" width="130">
That's 670 chars just to do that, and it assumes the list always has at least 6 elements.
The same output (better, since it handles any list size) would be accomplished with:
ListCombine(Transform(<img src="E:\JRiver\Actors\Left([L],1)\[L].png" width="130">,,[Actors]),,, )
(Note: I'm using ListJoin() which does not exist, because I just realized that ListCombine() is meant to join 2 lists into 1 - I think there's nothing like ListJoin yet - to join list elements into a single string - and it would also be useful)The idea is that each element of [Actors] gets inserted into the template in turn, replacing the placeholder [L]. If a list has 5 elements, this transform is done 5 times, returning a new list where each element is the "template" with the [L] replaced with the original element.
Sample implementationHere's a naive implementation example in metacode (corner cases not handled):
Transform(template, separator, SourceList) {
var transformed=new List<string>();
foreach (string item in SourceList.Split(separator))
string newItem = template.Replace("[L]", item)
transformed.Add(newItem)
return transformed.Join(separator);
}
Transforming multiple listsI placed the List argument in last place because the function can be expanded to take any number of lists:
Transform(template, separator, List1, List2, List3...)In this case, the template could include placeholders referencing each of the lists - I proposed [L1], [L2], [L3], etc. [L] could be a shorthand for [L1] when there's only one list. We could also have [N] for the current loop index (item position in list).
For instance, assume your have 3 lists:
[Tracks] = "Track1; Track2; Track3"
[Durations] = "3:45; 2:50; 4:27"
[Bitrates] = "224; 224; 160"
Transform("Song #[N]: [L1] ([L2] @ [L3] Kbps)",, [Tracks], [Durations], [Bitrates])
This would output a list of 3 elements:
Song #1: Track1 (3:45 @ 224 Kbps); Song #2: Track2 (2:50 @ 224 Kbps); Song #3: Track3 (4:27 @ 224 Kbps)
Sample implementation for multiple lists:(needs bounds checks to handle cases where the number of elements on each list is different - just use "" if there's no element for a given index)
Transform(template, separator, list<list<string>> Lists) {
var transformed=new List<string>();
int max = HighestElementCount(Lists);
for (int n = 0; n < max; n++) {
string newItem = template.Replace("[N]", n);
newItem = newItem.Replace("[L]", Lists[n][0]);
for (int x = 0; x < Lists.Count(); x++)
newItem = newItem.Replace("[L{x+1}]", Lists[n][x]);
transformed.Add(newItem)
}
return transformed.Join(separator);
}
I used placeholders like [N], [L], [L1] etc because there are already similar placeholders in regex functions [R1], [R2], etc. Other placeholder format can be used, of course.
OK, I hope this is not too complex for implementation
Let me know if some point is not clear.
Zybex
EDIT: fixed 2nd algorithm