groovy: adding and removing elements from a defined variable within a class - list

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.

Related

How to verify no null elements in list, Kotlin

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()

Kotlin prepend element

I am searching for Kotlin alternative to:
(cons 1 '(2 3)) in lisp or
1 : [2, 3] in haskell or
1 :: List(2, 3) in scala,
(which all result in sth like [1, 2, 3])
so I can prepend an element to a List<T> (or any other list you can offer).
It will also be fine if one could provide O(1) head and tail Kotlin alternatives (I've found just first())
I think the easiest would be to write:
var list = listOf(2,3)
println(list) // [2, 3]
list = listOf(1) + list
println(list) // [1, 2, 3]
There is no specific tail implementation, but you can call .drop(1) to get the same. You can make this head\tail more generic by writing these extension properties:
val <T> List<T>.tail: List<T>
get() = drop(1)
val <T> List<T>.head: T
get() = first()
Then:
val list = listOf(1, 2, 3)
val head = list.head
val tail = list.tail
Some more info: Kotlin List tail function
Any class which implements Deque will suitable for you, for example LinkedList:
val linkedList = LinkedList(listOf(2, 3))
linkedList.push(1)
println(linkedList) // [1, 2, 3]
Creating lists throught constructor LinkedList(listOf(2, 3)) in many places can be annoying, so feel free to write factory method:
fun <T> linkedListOf(vararg elements: T): LinkedList<T> {
return LinkedList<T>(elements.toList())
}
// Usage:
val list = linkedListOf(2, 3)
list.push(1)
println(list) // [1, 2, 3]
Simple, just wrap the element to prepend in a List and then use the + operator (or List.plus()) to concatenate the two Lists:
val list1 = listOf(2, 3) // [2, 3]
val list2 = listOf(1) + list1 // [1, 2, 3]
For your second question, in Kotlin 1.2 there are:
List.first()
List.last()
Both are O(1)
This could be done easily with extension functions as below
Prepending element
fun <T> MutableList<T>.prepend(element: T) {
add(0, element)
}
Prepending list
fun <T> MutableList<T>.prependAll(elements: List<T>) {
addAll(0, elements)
}
Inserts an element into the list at the specified index.
abstract fun add(index: Int, element: E)
Thus answer is
list.add(0,element)
If you do that often in your code for some reason, consider adding an extension operator method such as:
operator fun <T> T.plus(tail: List<T>): List<T> {
val list = ArrayList<T>(1 + tail.size)
list.add(this)
list.addAll(tail)
return list
}
Then your code could work Scala-like: 1 + listOf(2, 3)
Another way to achieve the same behaviour, shorter but sacrifices some memory:
operator fun <T> T.plus(tail: List<T>): List<T> {
return mutableListOf(this).apply {
addAll(tail)
}
}
To be as close to Lisp as possible consider using immutable linked list.
You can use pcollections
val list = ConsPStack.from(listOf(2, 3))
val newList = list + 1
println(list) // [2, 3]
println(newList) // [1, 2, 3]
Head:
list.first() // 1
list[0] // 1
(unfortunately this thing needs one allocation)
Tail:
list - 0 // [2, 3]
list.subList(1) // [2, 3]
Looks rather ugly.
Hopefully we'll get better API when kotlinx.collections.immutable will be ready. It's an effort to create standard Kotlin immutable collections (not just read-only ones that we currently have). As of now this project is still at very early stage (I was unable to find structure that supports efficient prepend/head/tail there)
I'm not entirely sure what you want to do, so please try one of the following.
Mutating list:
val list = mutableListOf(3, 2)
list.add(1)
Copping an immutable list:
var list = listOf(3, 2)
list = list + 1

(Scala) Keeping the structure of a list in the output

I need a little assistance.
I've been working out the functional aspects in Scala. Almost all the work is in lists and for the most part, I can work out the problems, but I hit a small dead-end. I can't keep the original form (structure) of the list in certain problems. In the output all the nested lists get flattened. Concatenate ::: flattens the list(that is an element of the original list) and append :: gives me a compilation error, as it requires a generic T type (not a list).
A very simple example, in which I want to remove the first element of a list that matches the input:
def removeFirst[T](obj: T, list: List[T]): List[T] = {
if (list isEmpty) Nil
else{
val fin: List[T] = list.head match {
case headAsList: List[T] => if (containsWithNestedLists(obj, headAsList))
removeFirst(obj, headAsList) ::: list.tail
else headAsList ::: removeFirst(obj, list.tail)
case _ => if (list.head == obj) list.tail
else if (list.tail == List()) List(list.head)
else list.head :: removeFirst(obj, list.tail)
}
fin
}
}
For one level deep lists, it works fine, but
the output that comes out for
removeFirst(1,List(List(1,2,3),1,2,3,4,5,6)) is List(2, 3, 1, 2, 3, 4, 5, 6), where as ideally I would want List(List(2,3),1,2,3,4,5,6)).
Or the more specific input removeFirst(1,List(List(2,3,List()),List(1,2,3),1,2,3,4,5,6,List(2,3,List())))
should have output = List(List(2,3,List()),List(2,3),1,2,3,4,5,6,List(1,2,3,List()))
Also I have found that removing the generic T and using Any in its place does the trick, but I also know that Any is a big no-no and a temporary solution for a permanent problem, as in other functions it hasn't helped.
As far as I know, I haven't seen a helpful solution on the internet, so I have to ask. Am I missing something, need to debug or is there another function that could help me? The closest I've come to my answer is using append :: in some manner, but I may be wrong.
You examples just look as if you want to remove a certain element from the list if it is present.
For flat lists you can do this much simpler:
def removeFirst[T](obj: T, list: List[T]) = list match {
case `obj` :: rest => rest
case _ => list
}
This will do the following:
> removeFirst(1, List(1, List(1,2,3)))
res57: List[Any] = List(List(1, 2, 3))
> removeFirst(1, List(2, List(1,2,3)))
res58: List[Any] = List(2, List(1, 2, 3))
> removeFirst(List(2,3), List(List(2,3), List(1,2,3)))
res59: List[List[Int]] = List(List(1, 2, 3))
However, it seems you want to do this for arbitrarily nested Lists. This is not directly possible, as Scala cannot express the exact type of that. The type you'd need would be something like
type NestedList[T] = List[T union NestedList[T]]
Scala does not have union types and you cannot do recursive definitions in this way, so you can not just do this either:
type NestedList[T] = List[Either[T, NestedList[T]]]
You can however do it, if you use a class instead of a type:
case class NestedList[T](value: List[Either[T, NestedList[T]]])
Now you can write your algorithm like this:
def removeFirst[T](obj: T, list: NestedList[T]): NestedList[T] = {
val rest = list.value match {
case Left(`obj`) :: tail => tail
case __ => list.value
}
NestedList(rest.map {
case Right(r) => Right(removeFirst(obj, r))
case Left(r) => Left(r)
})
}
And you can do this:
> removeFirst(1, NestedList(List(Left(1), Left(2), Right(NestedList(List(Left(1),Left(3)))))))
res71: NestedList[Int] = NestedList(List(Left(2), Right(NestedList(List(Left(3))))))
It is of course a bit cumbersome to build and decompose these structures. So maybe it would be better to build a proper tree class using a sealed abstract class and two case classes instead of using the Either.

Printing part of list starting from end and "loop" back to beginning not working

>>> mylist = [ 1, 2, 3 , 5, 'd']
>>> print 'mylist[-1:2] = ',mylist[-1:2]
output is an empty list: []
I am testing around with lists and from what I have so far understood from tutorials made me think the output would be [d, 1, 2]
Can anyone please help me out why isn't that the output?
To understand why your code returns an empty list, it is important to note how accessing list elements in python works. Indexing with : on a python list (or slicing) works like this:
a_list[start:stop:step]
stop must always be greater than start for the list indexing/slicing to work.
When you access an element in the list by using a negative number as the index, say a_list[-1], python adds the length of the list to it and gives you what you want. For ex:
a_list = [1, 2, 3, 4, 5]
a_list[-1] == a[5 - 1]
So when you do mylist[-1:2] it actually means mylist[4:2]. This violates start < stop condition. And hence returns an empty list.
This is what you are looking for:
[mylist[-1]] + mylist[:2]
Slicing with negative numbers (see string slicing) does not make the list a ringbuffer. It's just another way of pointing to an element in the list. So, what you ask for is really: The list beginning at index 4 and ending at index 2. Doesn't make sense, hence you get nothing.
Slicing does not work that way in python. Instead, I suggest creating your own defined function, like below:
>>> def loop(list, start, end):
... array = []
... for k in range(start, end+1):
... array.append(list[k])
... return array
...
>>> x = [1, 2, 3, 4, 5]
>>> desired_output = [5, 1, 2, 3]
>>> loop(x, -1, 2)
[5, 1, 2, 3]
>>> loop(x, -1, 2) == desired_output
True
>>>
This loops over the list, and adds each value of the list to another array, which it then returns.
Or, you can add them together using the following code:
[x[-1]] + x[:2]

Get the first element of a list idiomatically in Groovy

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]