12

Is there a better way to do this? Note: part1, part2 and part3 are string variables defined elsewhere (they can be null).

def list = [part1, part2, part3]
list.removeAll([null])
def ans = list.join()

The desired result is a concatenated string with null values left out.

Ryan
  • 1,370
  • 1
  • 13
  • 31
  • You can pack it all in to one line: `def ans = [part1, part2, part3].removeAll([null]).join()`, but I'm not sure that's quite what you mean by "better". – cdeszaq Mar 19 '12 at 18:49
  • @cdeszaq That might be better, but it does not work. The removeAll() method returns a Boolean, and join() cannot be called on a Boolean. – Ryan Mar 19 '12 at 18:51

4 Answers4

13

You can do this:

def ans = [part1, part2, part3].findAll({it != null}).join()

You might be able to shrink the closure down to just {it} depending on how your list items will evaluate according to Groovy Truth, but this should make it a bit tighter.

Note: The GDK javadocs are a great resource.

cdeszaq
  • 30,869
  • 25
  • 117
  • 173
9

If you use findAll with no parameters. It will return every "truthful" value, so this should work:

def ans = [part1, part2, part3].findAll().join()

Notice that findAll will filter out empty strings (because they are evaluated as false in a boolean context), but that doesn't matter in this case, as the empty strings don't add anything to join() :)

If this is a simplified question and you want to keep empty string values, you can use findResults{ it }.

epidemian
  • 18,817
  • 3
  • 62
  • 71
  • This is essentially the same as my answer with the addition of confirming how `findAll` works, right? – cdeszaq Mar 19 '12 at 20:40
  • It also removes the closure passed to `findAll` and mentions `findResults`, which might be useful for other cases. – epidemian Mar 19 '12 at 20:43
  • Good point. `findResults` has the nice ability to transform things as it filters. +1 – cdeszaq Mar 19 '12 at 20:47
  • I do like this, but it fails for me. I am using Groovy 1.7.10, and the findAll() method throws an error when one of the array elements is null. – Ryan Mar 19 '12 at 20:51
  • 1
    @Ryan Yeah, the docs says the niladic `findAll` was added in Groovy 1.8.1 – epidemian Mar 19 '12 at 20:59
2

Alternatively, you can do this as a fold operation with inject:

def ans = [part1, part2, part3].inject('') { result, element -> 
    result + (element ?: '')
}

This iterates the whole list and concatenates each successive element to a result, with logic to use the empty string for null elements.

ataylor
  • 64,891
  • 24
  • 161
  • 189
  • 1
    +1 Inject is a much more powerful way than my answer. It _might_ be a bit more complex and harder to understand though. – cdeszaq Mar 19 '12 at 20:42
1

You could use grep:

groovy:000> list = ['a', 'b', null, 'c']
===> [a, b, null, c]
groovy:000> list.grep {it != null}.join()
===> abc
Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • 1
    You could also just use `.grep()` since it defaults to using Groovy Truth as it's filter, but this is the same as using `findAll()`. – cdeszaq Mar 19 '12 at 20:46