Let the code speak first
def bars = foo.listBars()
def firstBar = bars ? bars.first() : null
def firstBarBetter = foo.listBars()?.getAt(0)
Is there a more elegant or idiomatic way to get the first element of a list, or null if it's not possible? (I wouldn't consider a try-catch block elegant here.)
Not sure using find is most elegant or idiomatic, but it is concise and wont throw an IndexOutOfBoundsException.
def foo
foo = ['bar', 'baz']
assert "bar" == foo?.find { true }
foo = []
assert null == foo?.find { true }
foo = null
assert null == foo?.find { true }
--Update Groovy 1.8.1
you can simply use foo?.find() without the closure. It will return the first Groovy Truth element in the list or null if foo is null or the list is empty.
You could also do
foo[0]
This will throw a NullPointerException when foo is null, but it will return a null value on an empty list, unlike foo.first() which will throw an exception on empty.
Since Groovy 1.8.1 we can use the methods take() and drop(). With the take() method we get items from the beginning of the List. We pass the number of items we want as an argument to the method.
To remove items from the beginning of the List we can use the drop() method. Pass the number of items to drop as an argument to the method.
Note that the original list is not changed, the result of take()/drop() method is a new list.
def a = [1,2,3,4]
println(a.drop(2))
println(a.take(2))
println(a.take(0))
println(a)
*******************
Output:
[3, 4]
[1, 2]
[]
[1, 2, 3, 4]
Related
I'd like to check a List<Int?> for nulls and if no nulls exist, then allow the List to proceed as a List<Int>, otherwise use an emptyList()
This is what I came up with:
var noNullElements: List<Int> = emptyList()
if (listWithPossibleNullElements.all { it != null }) {
noNullElements = listWithPossibleNullElements as List<Int>
}
//do something with noNullElements list
I'd be shocked if this was the best, most idiomatic way.
Solution
There are many acceptable solutions below, but the one I chose was a combination of the solutions
fun getSafeList(list: List<Int?>): List<Int> =if (null in list) emptyList() else list.requireNoNulls()
Here's a one liner extension function:
inline fun <reified T : Any> Iterable<T?>.filterNoneNull(): Iterable<T>? =
takeIf { null !in it }?.requireNoNulls()
takeIf {} - a scope function that will return null if the lambda evaluates to false
null !in it - use the in operator function to determine if the list contains null
finally, if takeIf {} returns a non-null value, filterNotNull() will convert the element type from the nullable T? to non-null T
Note that it will return null if the provided Iterable<T?> contains null, else List<T>, in case it's important to differentiate between the provided list being empty, or containing null. An alternative can be provided using the elvis operator.
Example usage - run in Kotlin Playground:
fun main() {
val listA: List<Int?> = listOf(1, 2, 3, null)
// since listA contains 'null', the result is 'null'
println(listA.filterNoneNull())
// prints: null
// provide an alternative, using the elvis operator
println(listA.filterNoneNull() ?: emptyList<Int>())
// prints: []
val listB: List<Int> = listOf(1, 2, 3)
// since listB does not contain null, the same list is returned
println(listB.filterNoneNull())
// prints: [1, 2, 3]
}
inline fun <reified T : Any> Iterable<T?>.filterNoneNull(): Iterable<T>? =
takeIf { null !in it }?.requireNoNulls()
Note: I edited the question and replaced filterNotNull() with requireNoNulls(), as the latter will not instantiate a new list
Check with contains for the existence of at least one null value:
val noNullElements = if (list.contains(null)) emptyList() else list.map { it!! }
Edit: Added this extension function:
fun List<Int?>.castToIntOrEmpty() =
if (this.contains(null)) emptyList() else this.map { it as Int }
val noNullElements = list.castToIntOrEmpty()
Example with no null elements:
val list: List<Int?> = List(10) { it }
// list is: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
val noNullElements = if (list.contains(null)) emptyList() else list.map { it!! }
println(noNullElements) // Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Example with some (or all) null elements:
val list: List<Int?> = List(10) { if (it % 2 == 0) it else null }
// list is: [0, null, 2, null, 4, null, 6, null, 8, null]
val nullElements = if (list.contains(null)) emptyList() else list.map { it!! }
println(nullElements) // Output: []
I think your problem is you want to take a generic List<Int?> type and treat it as a List<Int>, which means casting it. Because List<Int?> isn't a subtype of List<Int> (although the inverse is true, as Joffrey points out in the comments) you basically have to perform an unchecked cast in this situation:
if (list.contains(null)) emptyList else list as List<Int>
The compiler isn't smart enough to determine that this is a safe cast at runtime (and you have to be able to make that guarantee yourself, e.g. ensuring the list isn't being modified elsewhere to include a null after the check passes) so you'll get an unchecked cast warning. The documentation on generics goes into your options, but if you really want to pass in a List<Int?> and treat it as a List<Int>, you'll have to suppress that warning:
An unchecked cast warning can be suppressed by annotating the statement or the declaration where it occurs with #Suppress("UNCHECKED_CAST")
I'd argue the more idiomatic approach is to just create a new List<Int> instead of trying to cast the original one to a different generic type, or to make the original list provider pass a List<Int>? instead (i.e. null if there were any non-null elements) which is maybe just moving the problem - but it really depends on what you're doing.
You can easily create filtered copies and compare it to the original to decide whether to use it, or write a for loop building a new list that short-circuits if you hit a null, all those kinds of things. If you want to check first and only copy if you need it, lukas.j's answer has more examples (including a couple that throw exceptions, like requireNoNulls()) so you have a lot of options, and there are different tradeoffs - it really depends on what you're doing and where the bottlenecks are (if any). Things can get a bit awkward when you work with generics, so some situations don't end up looking as neat as you'd like!
Try using filterNotNull:
val noNullElements: List<Int> = listWithPossibleNullElements.filterNotNull()
This code: p [1, 2].each{ "foo" } produces nil, whilst I want it to put [1, 2] after iteration. How-to in Crystal?
Use tap:
p [1, 2].tap &.each { "foo" } # => [1, 2]
It yields self to the block and then returns self.
Another option (not preferable) could be creating a custom method that simply returns self after doing each:
class Array
def each_with_self
each { |x| yield x }
self
end
end
p [1, 2].each_with_self { "foo" } # => [1, 2]
For the case you are asking it could be enough to use parens in p(..) since p returns the argument as result.
p([1, 2]).each{ "foo" }
This behavior of p serves for doing easy inspections in the middle of an expression, i.e. changing foo(bar, baz) to foo(p(bar), baz).
As for #each, in crystal it was decided to return nil to improve the generated code since the value is not used most of the time. This also prevents the generation of some unions at the end of the day.
I have the following class
class A:
def __init__(self, elements):
self.elements = elements
I need to write a function that takes two instances of it, and finds if instance 1 is in the elements of instance 2. This is an irregular list, because those elements contain more instances of A to an arbitrary depth.
I want something along those lines:
def is_element_in(instanceA1, instanceA2):
found = False
for inherit in instanceA2.instanceof.inherits:
if instanceA1 == inherit:
found = True
else:
n_inherit(instanceA1, inherit)
return found
What's the best way to write this? I read some answers about flattening the list. I don't know if it's the best idea here, because I have to access fields to get my list of elements. Any python libraries that can be used here?
A possible solution is
def is_element_in(items, element):
for item in items:
if item == element:
return True
if isinstance(item, list) and is_element_in(item, element):
return True
return False
items = [[1, 2], [3], [[4], 5]]
print(is_element_in(items, 4))
print(is_element_in(items, 0))
Prints
True
False
I'm trying to get this class to run but I keep running into issues. I'm new to Java and not sure if I am doing this correctly. If someone could just help me out with the addition of elements to a list I can figure out the rest!
class ListPractice implements Testable {
def mylist = [4,5,6]
/**
* Adds a set of elements to the mylist variable
*
* #param elts The elements to be added
*/
def addToList(List elts) {
def newlist = getMylist()+List
return newlist
}
#Override
void testMe() {
addToList([7,8,9])
assert getMylist() == [4,5,6,7,8,9]
assert getMylist() == [7,8,9]
}
}
You are adding List instead of elts. The method you are looking for is addAll:
groovy:000> l = [1,2,3]
===> [1, 2, 3]
groovy:000> l.addAll([4,5,6])
===> true
groovy:000> l
===> [1, 2, 3, 4, 5, 6]
Since addtoList sounds already as if you plan to mutate this, why create a
new one, return it, and later never use it? So: mylist.addAll(elts) should
be enough.
related:
just write mylist instead of getMylist() - it's groovy
your comment on addToList says set but accepys a list. Sets have
different characteristics than lists, so it's confusing. If you rename it
to addToMylist you might not even need a comment at all.
List Destructuring (Multiple Assignment) in Groovy can be used to bind values to variables from a list. For example:
def (first, second, third) = [1,2,3,4,5,6]
assert third == 3
Is there a syntactical way to achieve the following:
def (first, second, <rest>) = [1,2,3,4,5,6]
assert rest == [3,4,5,6]
If not, what is closest/grooviest way to achieve the same result, preferably in single expression?
What you need to do is transform the list from six to three elements in the way that you describe. I.e. transform [1,2,3,4,5,6] to [1,2,[3,4,5,6]]. You probably also want this to be adjustable to any number of elements.
Here is a solution where a new method reduce is added to List which transforms the list in the proposed way:
List.metaClass.reduce = { int size -> delegate[0..size-2] + [delegate[size-1..-1]] }
def (first, second, rest) = [1,2,3,4,5,6].reduce(3)
assert first == 1
assert second == 2
assert rest == [3,4,5,6]
Edit: Last night, when going to sleep, I thought about using with to achieve this as a one liner. It's the same idea as above, though more cryptic (less readable) since the logic is inlined.
def (first, second, rest) = [1,2,3,4,5,6].with { it[0..1] + [it[2..-1]] }
assert first == 1
assert second == 2
assert rest == [3,4,5,6]
I don't think you can use multiple assignments to achieve this. Here's one option:
def list = [1,2,3,4,5,6]
def first = list[0]
def second = list[1]
def rest = list[2..-1]
Closest I could reach is:
Option 1: If toying with metaClass sounds like good idea:
List.metaClass.destructure = { ...n->
n.collect { delegate[it] }
}
def (a, b, rest) = [1,2,3,4].destructure(0, 1, 2..-1)
Options 2. Otherwise a good old method to the rescue:
def destructure (list,...n) {
n.collect { list[it] }
}
def (a, b, rest) = destructure([1,2,3,4], 0, 1, 2..-1)
Option 3. An inline but little ugly solution
def (a, b, rest) = [0, 1, 2..-1].collect { [1,2,3,4][it] }
All of above pass the criteria
assert rest == [3,4]
A variation on the solutions already offered that use with() + closure and collect() + closure. This solution uses only a closure with varargs:
def (first, second, rest) = { ... a -> a[0..1] + [a[2..-1]]} (1,2,3,4,5,6)
println first
println second
println rest