IBatis Dynamic Query Based on Length of String Array - ibatis

I have a DAO method which accepts as a parameter a HashMap.
The key in the HashMap is the name of the column to be searched.
The String[] contains the potential values to be searched for.
If the String array is of length 1, the where clause matches the exact value in the string array.
If the String array is of length 2, the where clause looks for all values BETWEEN the two values in the string array.
Ibatis does not seem to have a mechanism for determining the length of an array in the sqlMap xml file (since length of arrays does not have a JavaBean getter/setter).
Is it possible in ibatis to conditionally detect the length of the string array and adjust the query to either an exact match or a BETWEEN statement?
For example, if the key is age and the value is 18, then all 18 year old users are returned. However, if the key is age and the values are 18 and 23, then all users between 18 and 23 are returned.
The isEqual tag initially looked quite promising, but it does not work with array.length since it does not have a getter/setter. Can ibatis determine the length of an array in the sqlMap?
Thanks.

I wrote some java code to convert my HashMap to have a List instead of String[] and ibatis worked much better with the List.size method.

Related

Aggregation $size: Issue when FieldPath field name contains a number in the path

I’m trying to get the size of an array so that I can use the number that it returns in a for loop. I’m using mongodb compass. I’m trying to use something like the projection below where 0 is an object inside of path and “here” is an array with 2 items.
$project
{
“alias” : {$size : “$this.is.the.field.path.0.here”}
}
However, this keeps returning an array size of 0. It works fine for field paths that don’t contain a number in their path but returns 0 if the path does contain a number. Is there a way to properly get the correct size of the array here[ ] which has a size of 2?
Using dot notation to specify an array index works in the query language, but not in aggregation.
For aggregation, use the $arrayElemAt operator.
Also note from the BSON specification:
Array - The document for an array is a normal BSON document with integer values for the keys, starting with 0 and continuing sequentially. For example, the array ['red', 'blue'] would be encoded as the document {'0': 'red', '1': 'blue'}. The keys must be in ascending numerical order.
If you have a document that has numeric keys starting at 0, it will be treated as an array.

How to concatenate multiple ranges within a Match function

I have a list of values that I would like to match against the combination of multiple ranges.
So, for example, my ranges are A1:A100 and B1:B100.
Instead of concatenating A with B in a new column C, i.e.
CONCAT(A1,B1)...CONCAT(A100,B100)
and then matching my value against that new column - I would like to do something like this:
MATCH(value,CONCATENATE(A1:B100),0)
And copy this down a column near my list of values.
I have a feeling this can be done with some sort of array formula...
Yes as an array formula:
=MATCH(value,$A$1:$A$100 & $B$1:$B$100,0)
Being an array formula it must be confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
Though they may seem similar in approach they are not. CONCATENATE will return a string not an array to the MATCH with all 200 values in one long string. Where the above will return 100 values, each row concatenated, as an array which can be used to search.
One further note, If performance becomes a issue, Array formulas are inherently slower, adding the helper column and using a regular MATCH will improve the responsiveness.
This should work, basically you just need to concatenate it yourself using &
=MATCH(D1,A1:A10&B1:B10,0)
D1 is the value you're trying to look for.
This is an array, so remember to hit Ctrl+Shift+Enter when you input it.

How to use a string from a single cell as an array in a function without VBA

How do I convert a string from a cell to a text array inside of a function, that should use the array, without using VBA and without adding the array into any other part of the document? It will be one of these arrays on more than 1000 rows. The string format is ^[a-zA-Z0-9.,-]*$ with "," as delimiter.
This is the functionality I would like to achieve
I have an excel table with the following columns
A: ID numbers to compare, separated by comma (delimiter can be changed if needed). About 100 ID's would be good to support at least.
B: ID (Each value on the rows in the column are unique but not sorted and can't be sorted because sorting is needed based on other criterias)
C: Value (Several rows in the column can have the same value)
D: Output the one ID of the comma separated ID's that has the highest value on its row
The problem part of the output
So far I have made a function which find the correct ID in column B based on the values in column C but only if I enter the string from column A as an array constant manually within the function. I have not managed to get the function to create the array itself from column A, which is required.
Working part of the code
In this code I have entered the values from column A manually and this is working as it should.
=INDEX({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},MATCH(MAX(INDEX(C$10:C$20,N(IF(1,MATCH({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},B$10:B$20,0))))),INDEX(C$10:C$20,N(IF(1,MATCH({"1.01-1","1.01-3","1.08-1","1.01-1-1A"},B$10:B$20,0)))),0))
Note that the start row is not the first row and the array is used 3 times in the function.
Code to try to convert the string to a text array
Not working but if wrapped in SUMPRODUCT() it provide an array to the SUMPRODUCT() function, of course not usable since I then can't pass on the array. The background to this code can be found in question Split a string (cell) in Excel without VBA (e.g. for array formula)!.
=TRIM(MID(SUBSTITUTE(A10,",",REPT(" ",99)),(ROW(OFFSET($A$1,,,LEN(A10)-LEN(SUBSTITUTE(A10,",",""))+1))-1)*99+((ROW(OFFSET($A$1,,,LEN(A10)-LEN(SUBSTITUTE(A10,",",""))+1)))=1),99))
The second code output the first item of the array and inserted in the first code do not change this result as it did when wrapping the second code in SUMPRODUCT().
Here is a picture of my simplified test setup in Excel for this case, identical to what is described above.
Simplified test setup
I'm not really sure what you are doing with your formula.
But to convert contents of a cell to a comma separated text array to be used as the array argument to the INDEX or MATCH functions, you can use the FILTERXML function. You'll need to educate yourself about XML and XPATH to understand what's going on, but there are plenty of web resource for this.
For example, with
A10: "1.01-1","1.01-3","1.08-1","1.01-1-1A"
The formula below will return 1.08-1. Note the 3 for the row argument to the INDEX function.
=INDEX(FILTERXML("<t><s>" & SUBSTITUTE(SUBSTITUTE(A10,"""",""), ",", "</s><s>") & "</s></t>", "//s"),3)

Using a string key to return a value from an array

I have a named array of 14 rows by 2 columns. The first has a string key (ie: Country), and the second an attribute (ie: Owner). I want to retrieve the Owner by supplying the Country.
I only know how to use =INDEX to retrieve values from named arrays, but that expects col/row numbers.
How might I achieve my requirement?
For the sake of an answer.
Feed the INDEX function with a MATCH function to provide the requisite row number, along the lines:
=INDEX(B:B,MATCH(A2,A:A,0))
VLOOKUP will work but INDEX/MATCH is more powerful (see) so if you are already comfortable with INDEX it might be better to add MATCH to your arsenal rather than to bother with V/H LOOKUP.

Fast unanchored text search for an array

The input: An array of strings, and a single string.
The task: Find all entries in the array where any substring of the entry matches the input string.
The input array can be prepared or sorted in any way required, and any auxiliary data structure required built. The time required to prepare the data structures is (within bounds of sanity) unimportant.
The goal is maximum speed on the search.
What algorithm would you use that isn't just a linear search?
Because it says time required to prepare data structures is unimportant, I'd hash it. The key is a string (specifically, a substring), and the value is a list of integers corresponding to indices in the array whose elements have the key as a substring.
To build, take each string in the array and determine all possible substrings of that string, inserting each such key-value pair into the hash table. If the key already exists, append the index to the list rather than inserting/creating a new list.
Once you build this hash table, it's as easy as O(1) grab the list based on the input string and return.
EDIT: Looking more closely at the question, it seems like you'd want to return the actual strings in the array, rather than their indices. The hash table approach will work either way.
You might want to build an index of all string suffixes. Look into suffix trees to find out how this could be done. Wikipedia article might be too generalized so here is an adapted algoritm:
Building index
for each string in array
get all its suffixes (there N suffixes for a string of length N) and store a reference to a string in an ordered associative container (OrderedMap> (index)
Searching
find an lower bound of your search term in index
move over an index starting from lower bound until index key won't stop being prefixed with the search term
a sum of all references you will find is your search result
There is N²/2 substrings for a string of length N but only N suffixes. So suffix based data-structure should be more memory effective that substring based.

Resources