skip to Main Content

Xplan Quick Xplain

A look at the string .join()

Strings redux: .join()

We covered an extensive range of string functions and abilities in our all about strings article, however we left out a few areas to cover them in more detail – join() is one of those areas.

What is the .join() function

.join() is an advanced string function that creates and returns a string result from any iterable item, the results are joined together by separators defined at the start of the function.

  • The built in iteration makes it a lot more powerful than other attributes we looked at when discussing strings
  • The result returned will always be a string – keep that in mind
  • The string separator must always be defined

This method can be incredibly useful and powerful in advanced coding but it also has good uses in every day coding such as with letters, rapid list creation and for code used in blocks of text.

The term might seem new but you are already familiar with the concept and have used it many times – essentially any time you’ve written a for statement or looped over a group or element.

  • An iterable item is anything that can be looped over
  • Iteration is the term for taking each item in a sequence of something, one after the other.
  • An iterable is anything that can appear on the right side of a for loop <:for item in $client.asset:>  In this example the $client.asset group is iterable.

How does it work

<:=string_seperator.join(any iterable group, sequence, field or element):>

  • string separator is the string element used the separate each item being joined.  It can be anything eg: ‘,’ or ‘ ‘ (for a space) or ” (for no space).  it is always placed before the .join as .join is part of the string class. 
  • Any iterable/sequence/field/element is just that.  We will go over some examples below using fields, lists and groups.


Using the xplan standard $client.client_interests multi field.  Multi fields aren’t iterable in their standard form but their .text and .value parameters are:

# MusicIPOTennis

<:=‘, ‘.join($client.client_interests.value):>
# Music, IPO, Tennis

** The .value and .text won’t always be the same.  Where they are different you are going to want to output the .text, however by default each character in a string (or text) is iterable, so without using .splitlines() you won’t get the desired result:

<:=‘, ‘.join($client.client_interests.text.splitlines()):>
# Music, IPO, Tennis


In a group we need to define the specific data we want to access and output, so we might use something like this:

<:=‘, ‘.join([str(name.dep_name) for name in $client.dependent]):>
# Jimmy, Jane, Joffery

In all of the above examples you can see .join() provides a quicker way,  than the traditional methods we might use.  It also includes punctuation (seperators) that would otherwise require more complex solutions such as those we discussed here.

How does it work continued

Below we will take a look at some more complex uses for join:

<:let depList = [str(name.dep_name) for name in $client.dependent]:>
<:=len(depList) > 1 and (‘ and ‘.join([‘, ‘.join(depList[:-1])] + depList[-1:])) or .join(depList):>

# Jimmy, Jane and Joffery

You can see, using join allows us to code a sequence or group of items in one sentence a lot cleaner and quicker than the previous ways we’ve looked at doing this (see here and here). 

Breaking it down

  • The iterable doesn’t need to be defined within the .join (as we did in the earlier example), you can see we’ve defined depList separately, creating a list of all the dependant’s first names from the $client.dependent group.
  • Because the iterable is a list, we can using slicing techniques to determine a) all the elements except the last item b) the last item.  Therefore where the ‘ and ‘, ‘,’ should be.
  • depList[:-1] # returns everything except the last result
  • depList[-1:] # returns the last result
  • This example uses the AND/OR structure, starting with the len > 1 and finishing with the alternative.  This allows the statement to account for if there is only one result or if there are multiple results that will need the ‘,’ ‘ and ‘ added.

Great for

  • One of the shortest and most efficient ways to achieve the desired result
  • Separation of the list (depList) and the output statement can make it clean and a lot easier to read than the alternatives we’ve looked at

Keep in mind

  • This approach is more complex and less familiar coding for a lot of people.  This means if changes or support are needed for items using this, it may take longer and / or a higher degree of technical knowledge required.
  • Depending on how the document is structured separating the sequence (depList) from encapsulation with the output statement can cause issues.  To negate this, ensure the seqeuence/iterable is defined locally near the output statement and not hidden or defined elsewhere (if possible). 

The ability for join to iterate a sequence within itself is one of the key advantages.  Below is how the same result would be achieved without join():

<:for item in depList:><:=len(depList)>1 and (’ and ‘+item if item in depList[-1:] else item+‘,’) or item:><:end:>
# Jimmy, Jane and Joffery

Other examples

<:let trustees=[str(item.preferred_name) if item.preferred_name else str(item.fname) if item.trustee_type.value==1 else str(item.company_name)]:>

Dear <:=len(trustees) > 1 and (‘ and ‘.join([‘, ‘.join(trustees[:-1])] + trustees[-1:])) or ”.join(trustees):>, Trustees of the <:=$client.superfund_name:>,

# Dear John and Jane…

.join() or str concatenation (+)

Generally, for basic string operations still using + (concatenation) is going to be the preferred method. It is typically quicker and easier to read than the join alternative. Ideally, stick to using join for the things it does best, which is inline iteration and creating lists, not for basic operations:

<:let fullName=str($client.preferred_name)+’ ‘+str($client.last_name) #concatenation:>
# John Smith

<:let fullName=’ ‘.join([str($client.preferred_name), str($client.last_name)]):>
# John Smith

Back To Top