This is the 22nd day of my participation in the August Wen Challenge.More challenges in August
seq.not_any
Seq.not_any (seq, fn) and seq.every are reversed, returning true if and only if fn(x) == false for every element in seq, and false for all others, indicating that no element in seq satisfies the particular predicate check:
## seq.not_any
println("There are not any elements in array is less than zero: "
+ seq.not_any(a, lambda(x) -> x < 0 end));
println("There are not any in range is less than zero: "
+ seq.not_any(r, lambda(x) -> x < 0 end));
Copy the code
There are not any elements in array is less than zero: true There are not any elements in range is less than zero: False #### seq.some seq.some(seq, fn) returns the first element in seq such that fn(x) == true, or nil if none is found:Copy the code
seq.some
println(“Find a element in array is greater than zero: ” + seq.some(a, lambda(x) -> x > 0 end)); println(“Find a element in range is greater than zero: ” + seq.some(r, lambda(x) -> x > 0 end)); println(“Find a element in list is starting with ‘c’: ” + seq.some(n, lambda(x) -> string.startsWith(x, “c”) end));
Copy the code
Find a element in array is greater than zero: 1 Find a element in range is greater than zero: 1 Find a element in list is starting with ‘c’: car
#### take_while 'take_while(sequence, pred)' is used to select the element from the sequence whose 'pred(element)' returns' true 'and return the new set:Copy the code
fn is_neg(x) { x < 0 }
let list = seq.list(-2, -1, 0, 1, 2, 3, 0, 99, -1000, 7); let result = take_while(list, is_neg); p(“result of take_while: #{result}”);
With 'take_while' we pick out all negative numbers from 'list' and print:Copy the code
result of take_while: [-2, -1, -1000]
Conversely, we can 'drop' all negative numbers using 'drop_while'. #### drop_whileCopy the code
let result = drop_while(list, is_neg);
p(“result of drop_while: #{result}”);
Drop all negative numbers from 'list'. The rest should be non-negative:Copy the code
result of drop_while: [0, 1, 2, 3, 0, 99, 7]
#### group_by 'group_by(sequence, keyfn)' can be used to group sets. It will apply the function 'keyfn' to each element in the set, return the group key, and then return the same key to the same list. Eventually return to a map mapping: ` {key1 - > [e1 and e2], key2 - > (e3 and e4),... } ` :Copy the code
let result = group_by(list, is_neg); p(“result of group_by: #{result}”);
Executing the code above prints:Copy the code
result of group_by: {false=[0, 1, 2, 3, 0, 99, 7], true=[-2, -1, -1000]}
'is_neg' returns true when negative numbers are encountered, false otherwise, so the final set becomes two groups. #### distinct 'DISTINCT (sequence)' is used to eliminate duplicate elements in a collection and return a collection without duplicates:Copy the code
let result = distinct(list); p(“result of distinct: #{result}”);
The outputCopy the code
result of distinct: [-2, -1, 0, 1, 2, 3, 99, -1000, 7]
You can see that the 0 repeating element is removed, leaving only one. #### reverse 'reverse(sequence)' is used to return the reverse result of a set, and only applies to sequential sets such as arrays and lists:Copy the code
let result = reverse(list); p(“result of reverse: #{result}”);
Prints a collection of inversions of list:Copy the code
list is: [-2, -1, 0, 1, 2, 3, 0, 99, -1000, 7] …… result of reverse: [7, -1000, 99, 0, 3, 2, 1, 0, -1, -2]
#### zipmap Next we will describe several functions used to generate sets, starting with 'zipmap(list1, list2)', which maps two sets into a single map in the order 'e1-> e2'. Let's look at an example:Copy the code
Let m = zipmap (tuple (” a “, “b”, “c”), seq. List (1, 2, 3, 4)); p(“type of m: ” + type(m)); p(“result of zipmap: #{m}”);
We pass in two collections to 'zipmap' and end up with a map:Copy the code
type of m: java.util.HashMap result of zipmap: {a=1, b=2, c=3}
If the two sets have different lengths, the shortest set is ended:Copy the code
Let m = zipmap (tuple (” a “, “b”, “c”), seq. List (1, 2, 3, 4, 5, 6)); p(“result of zipmap: #{m}”);
The result is still {a=1, b=2, c=3} '. #### concat 'concat(seQ1, seq2)' is used to join two sets to generate a new set with complexity in O(m+n) where m and n are the lengths of two sets respectively:Copy the code
let c = concat(tuple(“a”, “b”, “c”), seq.list(1, 2, 3, 4)); p(“result of concat: #{c}”);
Output:Copy the code
result of concat: [a, b, c, 1, 2, 3, 4]
Suppose you have a scenario where you get a java.sql.ResultSet from the User table in the database, and you want to pass it into AviatorScript to process it, and you want to use the various functions mentioned above. Then you can implement a SEQ wrapper for 'ResultSet' :Copy the code
package com.googlecode.aviator.example.seq;
import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import com.googlecode.aviator.runtime.type.Collector; import com.googlecode.aviator.runtime.type.Sequence; import com.googlecode.aviator.runtime.type.seq.ListCollector; import com.googlecode.aviator.utils.Reflector;
/ * *
- A sequence wraps java.seql.ResultSet
- @author dennis([email protected])
*/ public class ResultSetSequence implements Sequence<Map<String, Object>> { private final ResultSet resultSet;
public ResultSetSequence(final ResultSet resultSet) { super(); this.resultSet = resultSet; }
@Override public Iterator<Map<String, Object>> iterator() { return new Iterator<Map<String, Object>>() {
@Override public boolean hasNext() { try { return ResultSetSequence.this.resultSet.next(); } catch (SQLException e) { throw Reflector.sneakyThrow(e); } } @Override public Map<String, Object> next() { try { Map<String, Object> user = new HashMap<>(); user.put("username", ResultSetSequence.this.resultSet.getString("username")); user.put("age", ResultSetSequence.this.resultSet.getString("age")); return user; } catch (SQLException e) { throw Reflector.sneakyThrow(e); } } @Override public void remove() { throw new UnsupportedOperationException(); }};Copy the code
}
@Override public Collector newCollector(final int size) { return new ListCollector(false); }
@Override public int hintSize() { // if we don’t known the exact row number, return 0. return 0; }
}
The core is the 'iterator' method, where we take the result of a row in 'next' and return it as a map object. You can then wrap this' ResultSet 'and throw it into AvaitorScript:Copy the code
package com.googlecode.aviator.example.seq;
import java.sql.ResultSet; import org.mockito.Mockito; import com.googlecode.aviator.AviatorEvaluator; import com.googlecode.aviator.Expression;
public class DemoResultSetSeq {
public static void main(final String[] args) throws Exception { // Mock a result set. ResultSet resultSet = Mockito.mock(ResultSet.class); Mockito.when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); Mockito.when(resultSet.getString(“username”)).thenReturn(“dennis”).thenReturn(“catty”); Mockito.when(resultSet.getInt(“age”)).thenReturn(30).thenReturn(20);
// Use it in aviator
Expression exp = AviatorEvaluator.getInstance().compileScript("examples/result_set_seq.av");
exp.execute(exp.newEnv("results", new ResultSetSequence(resultSet)));
Copy the code
}}
We first used mockito to simulate a 'ResultSet', which will return two rows:Copy the code
username, age
dennis, 30 catty, 20
Then wrap the resultSet into 'ResultSetSequence' and pass it as the 'results' variable to the script' examples/result_set_seq.av ':Copy the code
examples/result_set_seq.av
let users = into(seq.list(), results);
println(“User names: “
- map(users, lambda(u) -> u.username end));
println(“users that age is greater than 30: “
- filter(users, lambda(u) -> u.age > 30 end));
println(“Total age: “
- reduce(users, lambda(n, u) -> n + u.age end, 0));
We first use 'into' function to extract the results from 'ResultSet', which is convenient for subsequent operations. Next, we use Map to obtain the variable name list of users, filter users over 30 years old, and calculate the total age number by reduce:Copy the code
User names: [dennis, catty] users that age is greater than 30: [] Total age: 50
Copy the code