4

Suppose I have a couple of arrays:

$a = 1,2,3
$b = 4,5,6

and I get the intersection (empty):

$c = $a |?{$b -contains $_}

I would expect $c to contain an empty list such that I could do:

$c.length

but I don't. I get a $null (which issues an exception when queried for .length). How can I get an empty list back instead?

John Strood
  • 1,859
  • 3
  • 26
  • 39
ekkis
  • 9,804
  • 13
  • 55
  • 105

3 Answers3

6

Wrap it in the array constructor:

$c = @($a | ? { $b -contains $_ })
Andy Lamb
  • 2,151
  • 20
  • 22
2

I would expect $c to contain an empty list

You shouldn't expect that, it's not a Python-style list comprehension which always builds a list - even if the list is empty.

It's a putting objects through the pipeline, through a filter test, and storing the pipeline output. If nothing gets through the filter, there's no output to store. The pipeline doesn't conjure up an empty array from nowhere - that would be misleading and annoying. This is where the answer about the array constructor comes from - wrapping with @( ... ) is building an array with the pipeline output as the contents, and no output means an empty array.

And you're taking risks by using .Length instead of .Count. e.g. if you did that with strings, then an intersection of nothing would return no length, an intersection of two items would return 2, but an intersection of one item would return the length of the string:

$a = 'abc','cde','def'
$b = 'ghi','jkl','def'

$c = $a |?{$b -contains $_}  #c = 'def'

$c.length  # 1 item, length 3

It's not a problem if you're working with numbers that have no length property, but I think it's a better idea to habitually use .Count for getting the number of items in a collection.

Also see this answer: https://stackoverflow.com/a/26513523/478656 for related discussion on Length vs. Count properties, and how they were changed in PSv3+ to make working with empty things easier.

Which brings me to your claim:

I get a $null (which issues an exception when queried for .length)

It ... doesn't?

($null).Length    # $null in PSv2, 0 in PSv4, PSv5.1.  No exception.

Unless you're running in 'strict' mode?

Community
  • 1
  • 1
TessellatingHeckler
  • 27,511
  • 4
  • 48
  • 87
  • 1
    with regards to the the exception... you're correct. it seems .length is special. the exception was being generated on a call to .GetType() which fails with a "You cannot call a method on a null-valued expression" – ekkis Dec 08 '16 at 21:12
  • 1
    I selected Esperento57's answer because it actually answers the question, but I +1 your response for being well thought-out and I do agree that .Count is a better approach and one that I will switch to – ekkis Dec 09 '16 at 00:34
1

other solution

$c = ($a |?{$b -contains $_}) ,@()
Esperento57
  • 16,521
  • 3
  • 39
  • 45