OR a list of booleans with Groovy in one line? - collections

I have a method in a groovy class that returns a list of booleans, but what I really want is the result with the values in this list OR'd together (see example below)
Example output:
def result1 = foo*.isDisplayed() // [false, false, false] (I want false)
def reslut2 = bar*.isDisplayed() // [true, true, true] (I want true)
def result3 = baz*.isDisplayed() // [true, false, false] (I want true)
I'm sure there is an appropraite Groovy collection method but I'm failing to find the right one.
Clearly, I could just loop over everything with a for loop ( for(boolean val : result)...) but I know there's a sexy one-liner.
I found a way (using .findResult! Not quite a beautiful 1-liner, but good enough. I'll leave this question up for a bit, and if no answer, I'll self-answer with this.
def result = (foobar*.isDisplayed().findResult { it == true ?: null } != null)
I still think there is a more elegant way...

Use any() if you want true in case of result3 (which actually is OR instead of AND).
def result1 = foo*.isDisplayed().any() // [false, false, false] (I want false)
def reslut2 = bar*.isDisplayed().any() // [true, true, true] (I want true)
def result3 = baz*.isDisplayed().any() // [true, false, false] (I want true)
On the contrary, if you need false for result3 (AND condition) then use every()
def result3 = baz*.isDisplayed().every() //AND gives false.
A simpler approach to the above code.
Mainly:
def result1, result2, result3
(result1, result2, result3) = [foo, bar, baz]
.collectNested{it.isDisplayed()}*.any()

Related

How do I create a function that would take a textfile, two logical operators for comment and blank lines?

I am to construct a function named read_text_file.
It takes in an argument textFilePath that is a single character and two optional parameters withBlanks and withComments that are both single
logicals;
textFilePath is the path to the text file (or R script);
if withBlanks and withComments are set to FALSE, then read_text_file() will return the text file without blank lines (i.e. lines that contain nothing or only whitespace) and commented (i.e. lines that starts with “#”) lines respectively;
it outputs a character vector of length n where each element corresponds to its respective line of text/code.
I came up with the function below:
read_text_file <- function(textFilePath, withBlanks = TRUE, withComments = TRUE){
# check that `textFilePath`: character(1)
if(!is.character(textFilePath) | length(textFilePath) != 1){
stop("`textFilePath` must be a character of length 1.")}
if(withComments==FALSE){
return(grep('^$', readLines(textFilePath),invert = TRUE, value = TRUE))
}
if(withBlanks==FALSE){
return(grep('^#', readLines(textFilePath),invert = TRUE, value = TRUE))
}
return(readLines(textFilePath))
}
The second if-statement will always be executed leaving the third if-statement unexecuted.
I'd recommend processing an imported object instead of returning it immediately:
read_text_file <- function(textFilePath, withBlanks = TRUE, withComments = TRUE){
# check that `textFilePath`: character(1)
if(!is.character(textFilePath) | length(textFilePath) != 1){
stop("`textFilePath` must be a character of length 1.")}
result = readLines(textFilePath)
if(!withComments){
result = grep('^\\s*#\\s*', result, invert = TRUE, value = TRUE)
}
if(!withBlanks){
result = grep('^\\s*$', result, invert = TRUE, value = TRUE)
}
result
}
The big change is defining the result object that we modify as needed and then return at the end. This is good both because (a) it is more concise, not repeating the readLines command multiple times, (b) it lets you easily do 0, 1, or more data cleaning steps on result before returning it.
I also made some minor changes:
I don't use return() - it is only needed if you are returning something before the end of the function code, which with these modifications is not necessary.
You had your "comment" and "blank" regex patterns switched, I corrected that.
I changed == FALSE to !, which is a little safer and good practice. You could use isFALSE() if you want more readability.
I added \\s* into your regex patterns in a couple places which will match any amount of whitespace (including none)

Detecting first iteration (cycle) in R loop (without counter)

I'd like to detect the first iteration in a loop within a function from inside the body of the loop (i.e., without using some counter variable defined outside the loop), and in the most flexible possible manner.
Here would be one basic solution, just to demonstrate the idea:
vect = c('x', 'y', 'z')
for (elem in vect) {
print(elem)
isfirst(elem, vect)
}
isfirst = function(ele, vec) {
if (ele == vec[1]) {
print('this is the first cycle!')
} else {
print('this is NOT the first cycle!')
}
}
The "problem" with this is that I want this function to be easily reusable in any loop: that means that it should not need loop-specific arguments such as elem and vect. That is: another loop might use e.g. for (my_item in my_list) etc., and so then the isfirst arguments would need to be modified correspondingly, e.g. isfirst(my_item, my_list). The ideal way would be to just have an isfirst() without any arguments needed.
I'm not sure whether this is even possible, but I welcome any ideas.
(About why I need this: I would simply want to provide users with a function that behaves differently based on whether or not the iteration is the first, and that they can flexibly use in any loop and don't need to make even this small adjustment of changing the arguments.)
Well, here is the closest I could get:
vect = c('x', 'y', 'z')
for (elem in enum(vect)) {
print(elem)
isfirst()
}
enum = function(vec) {
assign("first_iteration", TRUE, envir = .GlobalEnv)
vec = mapply(c, 1:length(vec), vec, SIMPLIFY = FALSE) # this is just a small extra, not related to the question
return(vec)
}
isfirst = function() {
if (first_iteration == TRUE) {
print('this is the first cycle!')
assign("first_iteration", FALSE, envir = .GlobalEnv)
} else {
print('this is NOT the first cycle!')
}
}
But I'm still hoping for a better solution.

Accessing elements of a map of maps using a string in Groovy

Given I have a map like:
def myMap = [ b : [ c:"X" ] ]
And a string
def key = 'b.c'
I'd like to see my options for using the key to get to the value 'X'.
I have come up with two ways of achieving this myself, but I am not very happy with these solutions:
1) Eval.me("theMap", myMap, "theMap.$key")
2) mayMap."$key.split('\\.')[0]"."$key.split('\\.')[1]"
Anyone has a better way of doing this in Groovy?
A convenient way is to use ConfigObject which implements Map.
def myMap = [b:[c:'X', d: 'Y'], a:[n:[m:[x:'Y']]]] as ConfigObject
def props = myMap.toProperties()
assert props['b.c'] == 'X'
assert props.'b.c' == 'X'
assert props.'a.n.m.x' == 'Y'
Pros:
No more splitting.
No more evaluating.
IMHO its not the ConfigObject, that does the trick, its the Properties (from ConfigObject.toProperties()). Look & try:
def props = new ConfigSlurper().parse("""
b {
c = 'X'
d = 'Y'
}
a {
n {
m {
x:'Y'
}
}
}""")
assert props['b.c'] == 'X'
assert props.'b.c' == 'X'
assert props.'a.n.m.x' == 'Y'
'passed'
Assertion failed:
assert props['b.c'] == 'X'
| | |
| [:] false
[b:[c:X, d:Y], a:[n:[m:[:]]], b.c:[:]]
at ConsoleScript7.run(ConsoleScript7:14)
and I really wish, the ConfigObject could be indexed with such combined keys like above

Storing the output of a function into a variable in R

I'm having trouble with storing the output of a function into a variable. I think it's best that I give some context to the problem I'm trying to work out.
Suppose that players "a" and "r" play a game of tennis, the runningScoreFn sums the pointHistory vector and puts everything together in a nice data.frame
runningScoreFn = function(pointHistory){
playerUni = c("a", "r")
cols = sapply(playerUni, function(thisPlayer){
cumsum(pointHistory == thisPlayer)
})
names(cols) = playerUni
cbind(pointHistory, as.data.frame(cols))
}
The oneEpxiermentGameFn that plays out a game of "a" v.s "r".The first player to win 4 points wins the game, but he must be ahead by at least 2 points. "r" has 60% chance of winning a point.
pRogerPoint = 0.6
oneExperimentGameFn = function(pRogerPoint){
game = c(rep("r",pRogerPoint * 100), rep("a", 100-pRogerPoint*100))
i = 4
keepGoing = TRUE
while(keepGoing){
whosePoint = sample(game, size=i, replace=TRUE)
if(sum(whosePoint=="r")-sum(whosePoint=="a")>=2){
success = TRUE
print(cbind(runningScoreFn(whosePoint),success=success))
keepGoing = FALSE
}else if(sum(whosePoint=="a")-sum(whosePoint=="r")>=2){
success = FALSE
print(cbind(runningScoreFn(whosePoint),success=success))
keepGoing = FALSE
}
i=i+1
}
}
pRogerGameFn shows the probability that Roger wins the game.
pRogerGameFn = function(pRogerPoint, NExperiments){
RogerGameFn = lapply(1:NExperiments,function(dummy){
ok=oneExperimentGameFn(pRogerPoint)
})}
Here I wish to store the output into the variable ok, but ok returns NULL. I think this has something to do with my oneExperimentGameFn.
I also tried ok = RogerGameFn, but ok also returns NULL.
there is nothing returning from the function oneExperimentGameFn.
If there is a specific value you want returned, insert a return(.) command at the end of the function (or wherever else appropriate).
If you simply want to catch the print statements, you can use capture.output(.):
ok <- capture.output(oneExperimentGameFn(pRogerPoint))

Have a nested dictionary in python, and would like to fine an efficient way to append to it

I am looking to find the best pythonic way to do this.
Nested dictionary looks something like this (main script):
my_dict = { test: {
test_a: 'true',
test_b: 'true
}
I am importing a module that has functions that return numeric values.
I am looking for a way to append to the my_dict dictionary from the dictionary returned from the module.
i.e. functions from module:
def testResults1():
results = 3129282
return results
def testResults2():
results = 33920230
return results
def combineResults():
Would like to combine results, and return a dictionary. Dictionary returned is:
# Looking for best way to do this.
test_results = { 'testresults1': 3129282,
'testresults2': 33920230
}
I then want to append the test_results dictionary to my_dict.
Looking for best way to do this as well.
Thank you in advance!
Are you looking for the dict.update() method?
>>> d = {'a': 1, 'b': 2}
>>> d2 = {'c': 3}
>>> d.update(d2)
>>> d
{'a': 1, 'b': 2, 'c': 3}
my_dict = {}
def testResults1():
results = 3129282
return results
def testResults2():
results = 33920230
return results
def combineResults():
suite = [testResults1, testResults2]
return dict((test.__name__, test()) for test in suite)
my_dict.update(combineResults())
print my_dict
import collections
my_dict = collections.defaultdict(lambda: {})
def add_values(key, inner_dict):
my_dict[key].update(inner_dict)
You can read about collections.defaultdict in the library docs here.

Resources