I have a function with an optional list of parameters :
cleanFolders(String... folders) {
other_function_called(param1,param2,param3)
}
This function calls another function which take exactly three parameters.
So, I want to use the list of parameters folders to call this other function :
if there is only one element in folders list, I call
other_function_called(folders[0],"none","none")
if there are two elements :
other_function_called(folders[0],folders[1],"none")
and for three elements :
other_function_called(folders[0],folders[1],folders[2])
How I can do this properly (not using many disgracious "if else") ?
Thanks
as Jeff writes, you can use * to unpack the varargs array.
However, this will give you MissingMethodException if the number of arguments is not matching.
For this case you could create a new array starting with the available values, that is then filled up with the remaining default values, so that unpacked it just matches the right number of arguments.
def spreadArgs = args + ["none"] * (3 - args.size())
other_function_called(*spreadArgs)
Related
This question already has answers here:
What does `:_*` (colon underscore star) do in Scala?
(4 answers)
Closed 2 years ago.
When seeing some co-workers' Scala-Spark code, sometimes I encounter that they use lists to filter dataframes as in this example:
val myList: List[String] = List("0661", "0239", "0949", "0380", "0279", "0311")
df.filter(col("col1").isin(myList:_*)
The code above works perfectly, this one, however, does not:
df.filter(col("col1").isin(myList)
What I don't understand is, what is that "colon underscore star" :_* exactly doing?
Thanks in advance!
It does mean "pass list as a separate parameters". It works for methods, that have a vararg argument, like "any number of strings", but not a List[String] version.
Spark's isin function has signature isin(list: Any*): Column, Any* means "any number of arguments of type Any". Not very descriptive, but here you can pass either any number of strings, or any number of cols.
With :_* syntax, you're saying to compiler "replace my list with varargs", it's equialent to writing .isin("0661", "0239" ...)
Also, since Spark 2.4.0 there's function isInCollection, that takes Iterable, so you can pass List there directly.
This is sometimes called splat operator. It is used to to adapt a sequence (Array, List, Seq, Vector, etc.) so it can be passed as an argument for a varargs method parameter:
def printAll(strings: String*):Unit = {
strings.foreach(println)
}
val fruits = List("apple", "banana", "cherry")
printAll(fruits:_*)
If any method contains any repeated parameter. If you want to pass any Iterable in the method's repeated parameter, to convert your Iterable to repeated parameter you will use :_*
def x(y:Int*):Seq[Int]={ // y:Int* is a repeated parameter.
y
}
x(List(1,2,3,4):_*) <--- you are passing List into repeated parameter
I need to create multiple dictionaries from a list. if list is ['dic1','dict2'], i want to creat two different dictionaries such as sample_dic1 and sample_dic2.
if I don't use loops, I'll just type:
sample_dic1=dict();sample_dic2=dict()
my question is how to do it in a loop from a name list.
I tried to put the list in loop while each value of the loop equal to dict().
However, it does not assign the left-hand side to dict().
di_list=['dic1','dict2']
for (a) in di_list:
'sample_{}'.format(a)=dict()
I also Tried this. it doesn't give any error. but doesn't work neigher
temp=dict()
di_list=['dic1','dict2']
for (a) in di_list:
temp[a]='sample_{}'.format(a)
temp[a]=dict()
so I want to creat these two dictrionaries from di_list values. with 'sample_{}'.format(a) I can creat my desired name, But binding it to dict() doesn't work. i.e,. sample_{}'.format(a)=dict()
I think you're mixing two things: variables names and values. Variable names do not have a real effective meaning and if you consistently change their names the program remains the same (in fact, it happens in most languages under the hood anyway).
Here is an option to refer to an arbitrary number of values by name, using a dictionary (name->value):
temp=dict()
di_list=['dic1','dict2']
for (a) in di_list:
temp['sample_{}'.format(a)] = dict()
Now you can verify the values are in fact there:
assert temp['sample_dic1'] == {} # True
assert temp['sample_dict2'] == {} # True
I'm trying to sample an item (which is one of the keys in a dictionary) from a list and later use the index of that item to find its corresponding value (in the same dictionary).
questions= list(capitals.keys())
answers= list(capitals.values())
for q in range(10):
queswrite = random.sample(questions,1)
number = questions.index(queswrite)
crtans = answers[number]
Here,capitals is the original dectionary from which the states(keys) and capitals(values) are being sampled.
But,apparently random.sample() method adds square brackets and single quotes to the sampled item and thus prevents it from being used to reference the list containing the corresponding values.
Traceback (most recent call last):
File "F:\test.py", line 30, in
number = questions.index(queswrite)
ValueError: ['Delaware'] is not in list
How can I prevent this?
random.sample() returns a list, containing the number of elements you requested. See the documentation:
Return a k length list of unique elements chosen from the population sequence or set. Used for random sampling without replacement.
If you wanted to pick just one element, you don't want a sample however, you wanted to choose just one. For that you'd use the random.choice() function instead:
question = random.choice(questions)
However, given that you are using a loop, you probably really wanted to get 10 unique questions. Don't use a loop over range(10), instead pick a sample of 10 random questions. That's exactly what random.sample() would do for you:
for question in random.sample(questions, 10):
# pick the answer for this question.
Next, putting both keys and values into two separate lists, then using the index of one to find the other is... inefficient and unnecessary; the keys you pick can be used directly to find the answers:
questions = list(capitals)
for question in random.sample(questions, 10):
crtans = capitals[question]
I want to write a program which will read in a list of tuples, and in the tuple it will contain two elements. The first element can be an Object, and the second element will be the quantity of that Object. Just like: Mylist([{Object1,Numbers},{Object2, Numbers}]).
Then I want to read in the Numbers and print the related Object Numbers times and then store them in a list.
So if Mylist([{lol, 3},{lmao, 2}]), then I should get [lol, lol, lol, lmao, lmao] as the final result.
My thought is to first unzip those tuples (imagine if there are more than 2) into two tuples which the first one contains the Objects while the second one contains the quantity numbers.
After that read the numbers in second tuples and then print the related Object in first tuple with the exact times. But I don't know how to do this. THanks for any help!
A list comprehension can do that:
lists:flatten([lists:duplicate(N,A) || {A, N} <- L]).
If you really want printing too, use recursion:
p([]) -> [];
p([{A,N}|T]) ->
FmtString = string:join(lists:duplicate(N,"~p"), " ")++"\n",
D = lists:duplicate(N,A),
io:format(FmtString, D),
D++p(T).
This code creates a format string for io:format/2 using lists:duplicate/2 to replicate the "~p" format specifier N times, joins them with a space with string:join/2, and adds a newline. It then uses lists:duplicate/2 again to get a list of N copies of A, prints those N items using the format string, and then combines the list with the result of a recursive call to create the function result.
I need to access to items stored in a parameter that represents selected elements in a multiselect. I pass selected items from gsp to controller with the following code into the remoteFunction:
params: '\'receiptItemsSelected=\' + jQuery(this).val()'
Now, following the code found in discussion here, I use the closure to get each value, but if I perform a multiselect, the size of receiptItemsSelected is always 1, but value is, for example, 1,2. To get values as a list I've done the following in the controller
params.list("receiptItemsSelected")
but it does not give me two elements if I select two items in the multiselect, but always one element.
The question is: if I select two elements, how can I get each element and use it in the controller? And how can I have that elemnts as Long and not as String?
Thanks
If you're parameters are being passed with string representation of a list, e.g.:
http://yoursite.com/?receiptItemsSelected=1,2,3
You have to split the value using normal Groovy string manipulation and perform the type conversion yourself:
def receiptsAsLongs = params.receiptItemsSelected.split(',')*.toLong()
If your parameters are passed with the convention of repeated parameters makes a list, e.g.:
http://yoursite.com/?receiptItemsSelected=1&receiptItemsSelected=2
Then grails can convert this to a list for you using params.list(), but you must do the final String to Long conversion:
def receiptsAsLongs = params.list('receiptItemsSelected')*.toLong()
params.list() is intended for multi-valued parameters, i.e. it will work if you have
receiptItemsSelected=1&receiptItemsSelected=2
You may have more luck using serialize() rather than val() to build the request body.