Argument list unpacking - terraform

I'm currently trying to retrieve the max value contained in a list, but the max() builtin accept a variable number of floats instead of a single list.
variable "my_list" {
default = [1, 2]
}
output map_out {
value = "${max(var.my_list)}"
}
Error: output.map_out: At column 3, line 1: max: argument 1 should be type float, got type list in:
There's a way to accomplish this?
I think I need something similar to the argument list unpacking in Python, but I don't know how to do this in Terraform.

Function "map" does not accept list, it only accept individual floats.
https://www.terraform.io/docs/configuration/interpolation.html#max-float1-float2-
so only that format will work.
output map_out {
value = "${max(var.my_list[0],var.my_list[1])}"
}
if the number of values can differ - may be sort will work instead.

Related

TypeError summing a list of integers

I'd like to find the sum of the elements in a list using a loop. I must be able to apply this generically if inputting different lists.
I have tried the simple
print(sum(numbers))
and it returns
TypeError: unsupported operand type(s) for +: 'int' and 'str'.
When I tried adding each individually, I found out that the list changes. The original list is [1, 3, 5, 7, 9]. When I added each element using
int(numbers[0]) + int(number[1]) # ...
when I get to index 4, there isn't a value for the index.
I'm a little unsure by what you mean, because you haven't included much code, but I believe I can answer part of it.
It's hard to know why you're having indexing errors without seeing the code you wrote, but I imagine Because you may have been removing them as you added them up.
Maybe try using an accumulator variable, which would result in python code that might look like
numbers = [1,2,3,4]
total = 0
for i in range(len(numbers)): #loops through for exactly the number of items in the list
sum = total + numbers[i]
This won't change any of the items in the list, leaving intact, and leaving you with the variable sum that is equal to the total sum of the list.

how to enable string and numeric comparison temporarily?

Given this simplified example to sort:
l = [10, '0foo', 2.5, 'foo', 'bar']
I want to sort l so that numeric is always before strings. In this case, I'd like to get [2.5, 10, '0foo', 'foo', 'bar']. Is it possible make numeric and string temporarily comparable (with strings always larger than numeric)?
Note it is not easy to provide a key function to sorted if you are thinking about it. For example, converting numeric to string won't work because "10" < "2.5".
A way that you might do this does involve passing a key to sorted. it looks like this:
sorted(l, key=lambda x:(isinstance(x str), x))
This works because the key returns a tuple with the type of x and its value. Because of the way tuples are compared. Items at index 0 are compared first and if it they are the same, then next two items are compared and so on if they also are the same. This allows for the values to be sorted by type (string or not a string), then value if they are a similar type.
A more robust solution that also can handle further types might use a dictionary in the key function like this:
sorted(l,key=lambda x:({int:0, float:0, str:1, list:2, set:3}[type(x)], x))
further types can be added as necessary.

How to write a function max_and_min that accepts a tuple containing integer elements as an argument?

Functions can only return a single value but sometimes, we may want functions to return multiple values. Tuples can come in handy in such cases. We can create a tuple containing multiple values and return the tuple instead of a single value.
Write a function max_and_min that accepts a tuple containing integer elements as an argument and returns the largest and smallest integer within the tuple. The return value should be a tuple containing the largest and smallest value, in that order.
for example: max_and_min((1, 2, 3, 4, 5)) = (5, 1)
I am told to use an iteration to loop through each value of the tuple parameter to find the maximum and minimum values. Also, I must use Python 3.x.
How do I do this? I am really clueless. Thanks for your help!
def max_and_min(values):
# Write your code here
You are looking to pass a variable number of arguments to a function. In python, you can get multiple arguments passed at invocation with the * notation:
def max_and_min(*arg):
return (max(arg), min(arg))
Note that the Python 3 min and max functions themselves accept a variable number of arguments.

Asterisks in front of array names in Groovy?

I'm a bit new to Groovy, so I'm sure this is one of those extremely obvious things...but it's difficult to search for via Google.
In other languages, asterisks tend to represent pointers. However, in this snippet of Groovy code:
byte[] combineArrays(foo, bar, int start) {
[*foo[0..<start], *bar, *foo[start..<foo.size()]]
}
I can only imagine that that's not the case. I mean, pointers? Groovy?
I'm assuming that this code intends to pass the members of foo and bar as opposed to a multidimensional array. So what exactly do the asterisks mean?
Thanks a lot for your help.
When used like this, the * operator spreads a List or Array into a list of arguments. That didn't help at all, did it? How about an example instead? Say we have this function:
def add(Number a, Number b) {
return a + b
}
And this List
def args = [1, 2]
We shouldn't do this:
add(args)
because the function expects two numeric arguments. But we can do this:
add(*args)
because the * operator converts the List of 2 elements into 2 arguments. You can use this operator with Lists and Arrays.

Methods for nearby numbers in Groovy

In groovy are there any methods that can find the near by numbers? For example :
def list = [22,33,37,56]
def number = 25
//any method to find $number is near to 22 rather than 33.
Is there any method for the above mentioned purpose, or i have to construct my own method or closure for this purpose.
Thanks in advance.
The following combination of Groovy's collection methods will give you the closest number in the list:
list.groupBy { (it - number).abs() }.min { it.key }.value.first()
The list.groupBy { (it - number).abs() } will transform the list into a map, where each map entry consists of the distance to the number as key and the original list entry as the value:
[3:[22], 8:[33], 12:[37], 31:[56]]
The values are now each a list on their own, as theoretically the original list could contain two entries with equal distance. On the map you then select the entry with the smallest key, take its value and return the first entry of the value's list.
Edit:
Here's a simpler version that sorts the original list based on the distance and return the first value of the sorted list:
list.sort { (it - number).abs() }.first()
If it's a sorted List, Collections.binarySearch() does nearly the same job. So does Arrays.binarySearch().

Resources