2

Situation

I want to concatenate string variables and string arrays in TypeScript like in this simple example:

// var1, var2: string
// arr1: string[]
const myString = 'result:' + var1 + ' ' + arr1.join(' ') + ' ' var2;

I don't want multiple spaces concatenated together and there shouldn't be any spaces at the end.

Problem

It is possible that those variables are set to '' or that the array is empty. These leads to multiple spaces concatenated together which I want to avoid.

Question

Is there a more elegant way to concatenate only the set variables separated with exactly one space?

Conditions

  • The solution should work with more variables/arrays
  • The solution should be a one-liner
8
  • 1
    const myString = 'result:' + [var1, ...arr1, var2].filter(s => s?.length ?? 0 > 0).join(' '); Commented Sep 9, 2020 at 8:32
  • 1
    @AluanHaddad Your solution looks really interesting but I don't understand it completely. Could you please write it as an answer and explain why you use s? and ?? and how they work? Thank you in advance. Commented Sep 9, 2020 at 8:48
  • 1
    It's called Optional chaining. My comment is almost exactly the same as @SpoonMeiser's answer, which I hadn't noticed. s?.length evaluates to undefined if s` is undefined or null, where s.length would throw. ?? a fallback Commented Sep 9, 2020 at 8:52
  • 1
    @AluanHaddad and that 0 > 0 part? Commented Sep 9, 2020 at 8:57
  • 1
    So, if s is null or undefined then s?.length will evaluate to undefined And undefined > 0 evaluates to false (as does undefined < 0) so s?.length ?? 0 specifies that 0 should be used as a fallback. The thought here is to treat null or undefined values as if they were empty strings, filtering them out. Commented Sep 9, 2020 at 9:02

3 Answers 3

6

You can use destructuring to concatenate everything into a temporary array, and then use filter to remove any empty elements before calling join on the lot.

let var1 = "var1";
let arr1 = ["one", "", "two"];
let var2 = ""

const myString = "result:" + [var1, ...arr1, var2].filter(s => s).join(' ');

console.log(myString);

Sign up to request clarification or add additional context in comments.

7 Comments

you can also move "result:" inside the array
instead of (s => s) you could write .filter(Boolean)
will this trim additional spaces from the word, for example let var1 = "xyz "? if not, then ll have to trim every element
@Ifaruki how is .filter(Boolean) an improvement over the identity function? Are there any advantages?
@winklerrr its the equivalent to .filter(el => Boolean(el)) it converts the value to an boolean and returns true or false. Its one of the few functions that you can write like this in the callback
|
1

Does this satisfy your requirements?

const strArr = ['result:' + var1, ...arr1, var2].map((a) => a.trim()).join(' ')

Update

As suggested, following handles

  1. empty string
  2. string with multiple spaces
  3. trim additional spaces
const strArr = ['result:' + var1, ...arr1, var2].map((a) => a.trim()).filter(Boolean).join(' ')

Update 2

If you are using ES2019, you could do this in single pass:

const strArr = 
['result:' + var1, ...arr1, var2]
         .flatMap((el) => Boolean(el.trim()) ? [el.trim()] :[]).join(' ')

1 Comment

I really like about your solution that you thought about the edge case where the variables could also include spaces! When you now integrate the filter function in your answer, it would completely fulfil my requirements.
0

You could try this: const cleanedResult = result.replace(/\s\s+/g, ' ').trim()

This would remove multiple spaces in your variables as well though.

If you do not want that you can try out this solution:

const result = 'result:' + (var1 ? var1 + ' ' : '')  + (arr1 ? arr1.join(' ') : '') + (var2 ? var2 + ' ' : '')

1 Comment

The usage of the ternary operator for every variable seems to be an overkill. Especially if I need to work with more variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.