ConcatList (ListA; ListB; Delim ) ::=
_headA = GetValue ( ListA ; 1 ) ;
_headB = GetValue ( ListB ; 1 ) ;
_vcA = ValueCount ( ListA ) ;
_vcB = ValueCount ( ListB ) ;
_tailA = RightValues ( ListA ; _vcA - 1 ) ;
_tailB = RightValues ( ListB ; _vcA - 1 )
_vcA ≠ _vcB ; "" ;
_vcA = 1 ; _headA & Delim & _headB ;
_headA & Delim & _headB & ¶ & ConcatList ( _tailA ; _tailB ; Delim )
As a variation on my predecessor's theme:
ZipLists ( listA ; listB ; delim ) =
Let ( [
vcA = ValueCount ( listA ) ;
vcB = ValueCount ( listB )
vcA = vcB ;
Let ( [
hA = GetValue ( listA ; 1 ) ;
hB = GetValue ( listB ; 1 ) ;
tA = RightValues ( listA ; vcA - 1 ) ;
tB = RightValues ( listB ; vcB - 1 ) ;
result = hA & delim & hB
List ( result ; Case ( vcA - 1 ; ZipLists ( tA ; tB ; delim ) ) )
THANKS to both of you! I will study your examples so I can learn what is going on. Apparently I made it too complex by passing a counter. Both of you decrease the lists each iteration until done.
basically I do share the ideas of the given proposals. Off course ther is the universal function at Brian Dunning's collection ("CustomList" of Agnes Barouh) but in this case it seems to be overkill. I gave it a try too with less intermediate calculation. You can directly copy the function and see from the first line the three expected parameters and their names.
//**COPY FROM HERE
// CustomFunction: ConcatLists ( alist; blist; delim )
// alist and blist must be of same cardinality!
// Author: V. Krambrich 22 APR 2014
acount = ValueCount ( alist);
bcount = ValueCount ( blist) ];
Case ( acount <> bcount; "Error!";
acount = 0; "";
GetValue (alist; 1) & delim & leftValue (blist; 1) &
ConcatLists ( RightValues ( alist; acount - 1) ; RightValues ( blist; acount - 1); delim )
In principle it would be easy to expand the function to deal with lists of different lengths...
Let us know how you finally decided to go!
Since time was a factor, I already used erlost's function. It served the purpose - thanks again erlost. But I also went ahead and installed yours with one minor typo change. Your //else clause should have been getValue (blist; 1) instead of leftValue (blist; 1). I like the error checking you did and the format with comments. When I get time, I'll probably go back and replace with your version - again the format and comments is more like what I do.
Mark, that was not a typographic error.
Since the new list shouöd be a "list" in FileMaker sense, i.e. lists' elements separated by <cr>, the else clause does this:
take the headvalue of the alist and strip the <cr>, concatenate the result with the value stored for a delimter, then add the headvalue of the blist WITHOUT stripping the <cr> -– thus creating a new list value befor further calling processing of the rest lists.
This way my function will always generate a valid list; either the empty list, here represented by the word "Error!", or a list with 1 or more values delimited by carriage return signs!
Then performance is an issue whenever you program, and less operations are usually faster than more operations.
Wow - Thanks. I see what the problem was. When I pasted your code into the custom function and clicked the "OK" button, FM said it couldn't find the "leftValue" function. I assumed it was a typo and replaced that with the GetValue function. I should have serached the function list and I would have found "leftValues" (with an "s"). I also now understand why the GetValues would not have worked - thanks for the explanation.
Only with CustomList (http://www.briandunning.com/cf/868), it would read :
$La = "A¶B¶C" ;
$Lb = "1¶2¶3" ;
$Lim = "|"
CustomList ( 1 ; ValueCount ( $La ) ; "GetValue ( $La ; [n] ) & $Lim & GetValue ( $Lb ; [n] )" )
Be careful also that there is no empty values in your list A and B, if it is established by List ()
otherwise, you can edit your list directly by CustomList
$Lim = "|"
CustomList ( 1 ; Get ( FoundCount ) ; "GetNthRecord ( FieldA ; [n] ) & $Lim & GetNthRecord ( FieldB ; [n] )" )
But maybe it's better to make a field A & "|" & B and make a list() or ListOf (forv13) of this field.