Groovy equivalent to OCL forAll - groovy

What is the Groovy equivalent to the forAll method in OCL?
Let's say that I have a list of items.
def items = new LinkedList<Item>();
What is the Groovy way to express a predicate that holds if and only if all items match a certain criteria?
The following code snippet does not work, because the inner return only jumps out of the current iteration of the each closure, not out of the forAll method.
boolean forAll(def items)
{
items.each { item -> if (!item.matchesCriteria()) return false; };
return true;
}
The following code snippet, which should do the trick, feels cumbersome and not Groovy-like.
boolean forAll(def items)
{
boolean acceptable = true;
items.each { item -> if (!item.matchesCriteria()) acceptable = false; };
return acceptable;
}
I am looking for a way to lazily evaluate the predicate, so that the evaluation would finish when a first non-matching item is found.

You can use every
items.every { it.matchesCriteria() }

In groovy that's very easy:
def yourCollection = [0,1,"", "sunshine", true,false]
assert yourCollection.any() // If any element is true
or if you want to make sure, all are true
assert !yourCollection.every()
you can even do it with a closure
assert yourCollection.any { it == "sunshine" } // matches one element, and returns true
or
assert !yourCollection.every { it == "sunshine" } // does not match all elements

Related

TWIG: Get the first item fulfilling a condition

I need to display the first item that fulfills some condition. Something I would normally do via construction like this pseudocode:
for(item in some_array)
if(some_condition(item)) {
some_action();
break;
}
The problem is I need to do that in TWIG and TWIG does not allow to break a for loop. How to do that then?
You could use a boolean to denote that you have processed the first item but it will continue to loop over the rest of the array:
set firstItemProcessed = false;
for(item in some_array) {
if(firstItemProcessed == false and some_condition(item) ) {
some_action();
firstItemProcessed = true;
}
}

Failed to add element to new ArrayList in Groovy

I am trying to simulate a multimap, each value of langVarMap is a list. When I add a new String to the list, I get the following error:
No signature of method: java.lang.Boolean.add() is applicable for argument types: (java.lang.String) values: [mm]
Here is the code snippet:
def langs = engine.languages as Set
def langVarMap = [:]
engine.models.each { model ->
def lang = (model.#language.text()) // String
def variant = (model.#variant.text()) // String
langs.add(lang)
if (langVarMap.get(lang)) {
def a = langVarMap.get(lang) //ArrayList
langVarMap.put(lang, a.add(variant))
}
else {
langVarMap.put(lang, [variant])
}
Thanks in advance.
Problem is with this line:
langVarMap.put(lang, a.add(variant))
ArrayList.add(E e) returns boolean not the list. Adding result of add action adds a boolean value of TRUE to the map after which cannot call add method on it. Need to rewrite as following:
if (langVarMap.get(lang)) {
def a = langVarMap.get(lang) //ArrayList
// a is already in langVarMap so don't need to put into ma again
a.add(variant)
} else {
langVarMap.put(lang, [variant])
}
And can further refine with this to remove the redundant lookup.
def a = langVarMap.get(lang) //ArrayList
if (a) {
a.add(variant)
} else {
langVarMap.put(lang, [variant])
}

How check if a list contains value or key inside a another list in Groovy?

How can I check if a list contains a key or value inside a sublist (of sublist ..) or in the "root"
And is possible to get a the "path"?
This containsValue or containsKey seems only to look in the root of the list
Example pseudo:
//This is my list
list = [languages:[_clazz:"basics.i18n.Language", messages:[_clazz:"basics.i18n.Message"]]]
list.containsKey("languages") // return true
list.containsValue("basics.i18n.Language") // return false where I want true
list.containsKey("messages") // return false // return false where I want true
list.containsValue("basics.i18n.Message") // return false where I want true
There's nothing in Groovy for this I don't think, but you can write your own and add them to Map (what you have is a Map, not a List as you have named the variable)
Map.metaClass.deepContainsKey = { value ->
delegate.containsKey(value) ?:
delegate.values().findAll { it instanceof Map }.findResult { it.deepContainsKey(value) } ?:
false
}
Map.metaClass.deepContainsValue = { value ->
delegate.containsValue(value) ?:
delegate.values().findAll { it instanceof Map }.findResult { it.deepContainsValue(value) } ?:
false
}
Then, given your map:
def map = [languages:[_clazz:"basics.i18n.Language", messages:[_clazz:"basics.i18n.Message"]]]
All of these assertions pass:
assert map.deepContainsKey("messages")
assert map.deepContainsValue("basics.i18n.Message")
assert map.deepContainsValue("basics.i18n.Language")
assert !map.deepContainsKey("missing")
assert !map.deepContainsValue("novalue")

UISearchController CONTAINS not finding partial results in Array of Dictionary

I am trying to use a predicate to search an array of dictionary objects for a string value (from a searchController). I am not getting any partial string matches. I need to search through many key-values for a match, so I am doing it as written in the code below.
My problem is that if I search: "Orida"
I am not Finding: "Florida"
I believe I have the Predicate set correctly...
self.filteredData.removeAll(keepCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %#", self.searchController.searchBar.text!)
let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredData = array as! [Dictionary<String, String>]
It is working correctly if I type the exact matching string that appears in any Value of the dictionary, but not if I search for a partial match...
This isn't a duplicate post - all of the existing posts about this that I've found either aren't searching multiple values (like multiple key-values in my dictionary) or are using the contains() method on strings themselves.
Update
I have tried the answer suggested below using filter:
let searchPredicate = NSPredicate(format: "SELF CONTAINS[cd] %#", searchController.searchBar.text!)
let array = (self.airportData as NSArray).filteredArrayUsingPredicate(searchPredicate)
self.filteredData = self.airportData.filter({(item: String) -> Bool in
var stringMatch = item.lowercaseString.rangeOfString(self.searchController.searchBar.text!)
return stringMatch != nil ? true : false
I get the following error:
'(String) -> Bool' is not convertible to '([String : String]) -> Bool'
I'm confused about how to get this to handle the dictionary of strings properly.
self.filteredData = self.airportData.filter({(item: String) -> Bool in
var stringMatch = item.lowercaseString.rangeOfString(self.searchController.searchBar.text!)
return stringMatch != nil ? true : false
})
Try to do this using the swift filter method on your array instead.
After a lot of advice from #pbush25, I was able to figure out an answer. It isn't exactly what I wanted, but it works. I was hoping to avoid specifying all the keys in the dictionary that I wanted to search the values of, but it ended up being the only way I could figure out to make it work. I would prefer to use the array.filter, but I couldn't figure out how to get that closure to cast as the right kind of array.
Functioning code:
let startCount = searchController.searchBar.text!.length
delay(1) {
if self.searchController.searchBar.text!.length >= 3 && self.searchController.searchBar.text!.length == startCount{
self.view.addSubview(self.progressHud)
self.appDel.backgroundThread(background: {
self.filteredData.removeAll(keepCapacity: false)
let searchText = self.searchController.searchBar.text!.lowercaseString
self.filteredData = self.airportData.filter{
if let ident = $0["ident"] {
if ident.lowercaseString.rangeOfString(searchText) != nil {
return true
}
}
if let name = $0["name"] {
if name.lowercaseString.rangeOfString(searchText) != nil {
return true
}
}
if let city = $0["municipality"] {
if city.lowercaseString.rangeOfString(searchText) != nil {
return true
}
}
return false
}
},
completion: {
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
self.progressHud.removeFromSuperview()
}
});
}
}

Groovy, collect objects following a property while not null?

Is there already a way in groovy to collect objects following a property while not null ?
Object.metaClass {
collectWhileNotNull = { Closure follow ->
def result = []
def previous = null
for (def current = delegate; !current.is(previous) && (current != null); current = follow(current)){
result << current
previous = current
}
return result
}
}
It is useful for recursive data structure.
An example of usage for a groovy.util.Node :
Closure getAncestors = { Node n -> n.collectWhileNotNull{ it.parent() }.tail().reverse() }
You can use a Generator class (this is also the name of the necessary pattern) from cookbook.

Resources