3
\$\begingroup\$

I want to join two fragments into one string with a separator, but when one of the fragments is empty I only want one of them.

I have two implementations. The first is long and slightly repetitive, but I believe it is easier to understand, since it is a more step-by-step description of the process. The second is way shorter, but less self-explanatory. It uses the Where method, and it may not be clear to everybody what the semantics of $_ are. Maybe both approaches can even be merged into an even better implementation.

Which would you recommend?

Version 1:

if ($Fragment1.Length -ne 0 -and $Fragment2.Length -ne 0) {
 $String = $Fragment2 + $Seperator + $Fragment2
} elseif ($Fragment1.Length -ne 0) {
 $String = $Fragment1
} elseif ($Fragment2.Length -ne 0) {
 $String = $Fragment2
} else {
 $String = $null
}

Version 2:

$String =
 @($Fragment2, $Fragment1).Where({$_.Length -ne 0}) -join $Seperator
asked Jun 5, 2020 at 15:38
\$\endgroup\$
9
  • \$\begingroup\$ As someone who doesn't use PowerShell I find the second easier to read. \$\endgroup\$ Commented Jun 5, 2020 at 15:44
  • \$\begingroup\$ OK, so you'd recommend V2? \$\endgroup\$ Commented Jun 5, 2020 at 15:45
  • \$\begingroup\$ Not really. I would use it. But I wouldn't recommend you to use it as you find it harder to read. \$\endgroup\$ Commented Jun 5, 2020 at 15:46
  • \$\begingroup\$ I'd like to make it clear that I'm not saying I dislike it. I am concerned about the readability of my code. I prefer version 2 myself. \$\endgroup\$ Commented Jun 5, 2020 at 15:49
  • \$\begingroup\$ No matter which implementation you choose, you should extract this code into a function called JoinSkipEmpty. This way it doesn't matter that much if the code is complicated or not since the name already expresses everything you need to know about the function. Oh, and please write Separator instead of Seperator. Your IDE should have told you this spelling mistake. \$\endgroup\$ Commented Jun 5, 2020 at 16:20

2 Answers 2

1
\$\begingroup\$

On PowerShell v6+, I would do the following:

$String = $Fragment1, $Fragment2 |
 Where-Object { -not [System.String]::IsNullOrWhiteSpace($_) } |
 Join-String -Separator $Separator

You could use [System.String]::IsNullOrEmpty() instead of [System.String]::IsNullOrWhiteSpace(), but I find [System.String]::IsNullOrWhiteSpace() to be the desired functionality in almost all cases.

On Windows PowerShell (versions prior to v6), the Join-String command doesn't exist. There I would use:

$String = ($Fragment1, $Fragment2 |
 Where-Object { -not [System.String]::IsNullOrWhiteSpace($_) }) -join $Separator

The @().Where({ ... }) method is fairly obscure, so I tend to avoid it.

it may not be clear to everybody what the semantics of $_ are.

I'm not sure it's valuable to consider this possibility. Simply put, if your reader doesn't understand the semantics of $_, then they cannot read PowerShell. It's a ubiquitous and pervasive variable both in practice and in design.

answered Jul 1, 2020 at 14:02
\$\endgroup\$
0
\$\begingroup\$

here is what i meant about the -join operator being the way to go. [grin] you DO need to filter out the blank/null items, but once that is done things work neatly. i included two filters ... the basic $_ test just uses the way that "nothing" and "blank" are coerced to booleans. the other uses the builtin [string]::IsNullOrEmpty() static method.

# build some string arays to test with
1ドルst = 'One', 'Two', 'Three'
2ドルnd = 'Wun', $Null, 'Tree'
3ドルrd = '', 'Too', ''
4ドルth = 'A', 'B', ''
$Separator = '-'
# the leading comma forces the arrays to remain individual arrays instead of merging into one
foreach ($Item in (,1ドルst + ,2ドルnd + ,3ドルrd + ,4ドルth))
 {
 'Original ...'
 $Item
 'Unfiltered [will glitch with empty items] ...'
 $Item -join $Separator
 'Filtered with basic ".Where()" test ...'
 $Item.Where({$_}) -join $Separator
 'Filtered with explicit test ...'
 $Item.Where({-not [string]::IsNullOrEmpty($_)}) -join $Separator
 '=' * 30
 }

output ...

Original ...
One
Two
Three
Unfiltered [will glitch with empty items] ...
One-Two-Three
Filtered with basic ".Where()" test ...
One-Two-Three
Filtered with explicit test ...
One-Two-Three
==============================
Original ...
Wun
Tree
Unfiltered [will glitch with empty items] ...
Wun--Tree
Filtered with basic ".Where()" test ...
Wun-Tree
Filtered with explicit test ...
Wun-Tree
==============================
Original ...
Too
Unfiltered [will glitch with empty items] ...
-Too-
Filtered with basic ".Where()" test ...
Too
Filtered with explicit test ...
Too
==============================
Original ...
A
B
Unfiltered [will glitch with empty items] ...
A-B-
Filtered with basic ".Where()" test ...
A-B
Filtered with explicit test ...
A-B
==============================
answered Jun 6, 2020 at 14:05
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.