Cache a variable in groovy - variables

When I try to access the len-variables at the end of the script I get this error: "Cannot iterate twice! If you want to iterate more that once, add _CACHE explicitely."
How can I fix that?
def src_str = query_string
def src_arr = src_str.split(' ')
def trg_arr = doc['my_index'].values
trg_arr_sorted = [:]
trg_arr.each {
_index['my_index'].get(it, _POSITIONS).each { pos ->
trg_arr_sorted[pos.position] = it
}
}
src_len = src_arr.length
def trg_len = trg_arr_sorted.size()
int[][] matrix = new int[src_len + 1][trg_len + 1]
(src_len + 1).times { matrix[it][0] = it }
(trg_len + 1).times { matrix[0][it] = it }
(1..src_len).each { i ->
(1..trg_len).each { j ->
matrix[i][j] = [matrix[i-1][j] + 1, matrix[i][j-1] + 1,
src_arr[i-1] == trg_arr_sorted[j-1] ? matrix[i-1][j-1] : matrix[i-1][j-1] + 1].min()
}
}
return 100 - (100 * matrix[src_len][trg_len] / max(src_len, trg_len)) // over here !!!
The code calculates a score using the levenshtein distance computed in words. It works perfect except of the scoring in the last line.

Okay problem is solved.
I explicitly had to declare cache and positions:
_index['lang'].get(it, _POSITIONS | _CACHE)
The error wasn't in the last line, but I thought so. I changed the script to debug it, but elasticsearch doesn't reload the new scipt instantly.

Related

Lua implementation of BestSum function using memoization

I am trying to translate the below javascript "bestSum" memoization function into lua:
const bestSum = (targetSum,numbers,memo ={}) => {
if(targetSum in memo) return memo[targetSum];
if(targetSum === 0 ) return [];
if(targetSum <0)return null;
let shortestCombination = null;
for (let num of numbers) {
const remainder = targetSum - num;
const remainderCombination = bestSum(remainder,numbers,memo);
if (remainderCombination !==null) {
const combination = [...remainderCombination, num];
if (shortestCombination === null || combination.length < shortestCombination.length)
{
shortestCombination = combination;
}
}
}
memo [targetSum] = shortestCombination;
return shortestCombination;
}
sample test cases with correct results:
console.log(bestSum(7,[5,3,4,7])); //[7]
console.log(bestSum(8,[2,3,5])); //[3,5]
console.log(bestSum(8,[1,4,5])); //[4,4]
console.log(bestSum(100,[1,2,5,25])); //[25,25,25,25]
I translated the above javascript into lua as the following:
local function BestSum(target_sum,numbers,memo)
if memo[target_sum] ~= nil then return memo[target_sum] end
if target_sum == 0 then return {} end
if target_sum < 0 then return nil end
local shortest_combination = nil
for i, num in ipairs (numbers) do
local remainder = target_sum - num
local remainder_combination = BestSum(remainder,numbers, memo)
if remainder_combination ~= nil then
local combination = remainder_combination
table.insert(combination,num )
if (shortest_combination == nil) or (#combination < #shortest_combination )then
shortest_combination = combination
end
end
end
memo[target_sum] = shortest_combination;
return shortest_combination;
end
but don't get the desired results for the two last cases...... instead get incorrect results:
BestSum(8,{1,4,5},{})==>{"4","1","4"}
BestSum(150,{5,25},{})==>
{"25","5","5","5","5","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25","5","25"}
The results are not even correct let alone being "best" case??
Can anyone spot where I'm going wrong?
Much appreciated
The problem is with this part of the translation:
local combination = remainder_combination
table.insert(combination, num)
Tables are pass by reference, so this isn't creating a new table, it's just assigning the variable combination to the same table. Modifying combination is just adding more data to remainder_combination.
The JavaScript version is taking care to create a new array, and fills it with the contents of the remainderCombination array (using '...', the spread operator):
const combination = [...remainderCombination, num];
This is the most accurate Lua translation:
local combination = {unpack(remainder_combination)}
table.insert(combination, num)
(Edit: For Lua 5.2+ it's table.unpack)

Ambiguous expression could be either a parameterless closure expression or an isolated open code block;

I'm having the following code block which will create an object with is concatenated string of all objects within "basixCertificateNumbers" array.
def object= jsonSlurper.parseText '''
{
"basixCertificateNumbers": [
{
"basixCertificateNumber": "012-012"
},
{
"basixCertificateNumber": "045-123"
}
]
}
'''
def concatdObj = jsonSlurper.parseText '''
{
"basixNumber" : ""
}
'''
def content = object.each{ entry->
if(entry.value.getClass().name === "java.util.ArrayList"){
for (basixIndex = 0 ; basixIndex < entry.value.size(); basixIndex++){
entry.value[basixIndex].each{ nestedEntry->{
concatdObj.basixNumber = concatdObj.basixNumber + nestedEntry.value + " "
}}
}
concatdObj.basixNumber = concatdObj.basixNumber.substring(0, concatdObj.basixNumber.length() - 1);
}}
I'm currently receiving the following errors:
Ambiguous expression could be either a parameterless closure expression or an isolated open code block;
solution: Add an explicit closure parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...} # line 41, column 56.
asixIndex].each{ nestedEntry->{
^
Even though the solution suggested is to put the label on it, I'm not sure where would be the optimal way to put it.
The current solution would be remove the "{" after nestedEntry, which will be something like this:
entry.value[basixIndex].each{ nestedEntry->
concatdObj.basixNumber = concatdObj.basixNumber + nestedEntry.value + " "
}
However, I believe this is not an optimal way of doing things, so if anyone would have a better idea. It would be a great help!
My desire output would be:
{
"basixNumber" : "012-012 045-123"
}
You can just do
def content = [
basixNumber: object.basixCertificateNumbers.basixCertificateNumber.join(' ')
]
String jsonOutput = new JsonOutput().toJson(content)
You don't need concatdObj

Unable to Parse the variable value to the array variable

I was trying to pass the variable 'i' value to a array index 'locations[i]' using below karate code. but throwing an error saying unable to parse. Please suggest be for any changes.
Feature: Verify Branches
Background: For loop implementation
Given url ''
When method GET
Then status 200
* def i = 0
* def z = $.locations[i].zip
* def p = $.locations[i].phone
* def fun =
"""
function(locations){
for (var i = 0; i < locations.length; i++)
{
print(i)
print('Element at Location ' + i +':' + p)
}
}
"""
Scenario: Validate the locations
Given url ''
When method GET
Then status 200
* call fun p
It is hard to make out anything since you have not provided the value of the response. There are many things wrong here. But I'll try.
Take this line:
* def z = $.locations[i].zip
This will not work, Karate does not support variables within JsonPath by default, refer the docs: https://github.com/intuit/karate#jsonpath-filters
And I think you are un-necessarily using JsonPath where normal JavaScript would have been sufficient:
* def z = response.locations[i].zip
Also it seems you are just trying to loop over an array and call a feature. Please refer to the documentation on Data Driven Features.
Take some time and read the docs and examples please, it will be worth your time. One more tip - before I leave you to understand Karate a little better. There is a way to convert a JSON array into another JSON array should you need it:
* def fun = function(x){ return { value: x } }
* def list = [1, 2, 3]
* def res = karate.map(list, fun)
* match res == [{ value: 1 }, { value: 2 }, { value: 3 }]
So there should never be a need for you to manually do a for loop at all.

React-Native number formatting

I'm currently using the react-native-globalize library to format numbers but when using:
<FormattedNumber value={10000000} useGrouping={true} />
Which is supposed to present a result like this:
> 10,000,000
But for some but reason it doesn't seem to be working at all and the output is the number with no separators.
Anyone knows how to solve this or another library I could use? (yes I have done my google research first).
Thank you guys!
You can use the method toLocaleString() provided by Javascript.
Use it as:
getFormattedNumber = number => {
let formattedNumber = Number.parseInt(number).toLocaleString('en-IN');
return formattedNumber;
}
You may use en-US based on your region.
If the above code fails in Android, try below steps:
Goto your android/app/build.gradle file
Change line def jscFlavor = 'org.webkit:android-jsc:+' to def jscFlavor = 'org.webkit:android-jsc-intl:+'
Above solution is here: https://blog.bam.tech/developer-news/formating-numbers-in-react-native
You can use this function simply.
const numberWithComma = x => {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
};
When you call this function:
numberWithComma(10000000)
the result should be as follows:
10,000,000
For example:
let val = 14234523;
... ...
<Text> {numberWithComma(val)} </Text>
Result:
14,234,523
numberFormat = (value) => {
var re = '\\d(?=(\\d{' + 3 + '})+' + '\\D' + ')';
var num = value.toFixed(Math.max(0, ~~2));
var str = num.replace(new RegExp(re, 'g'), '$&' + ',');
return str;
}
Use:
numberFormat(4000)
Result:
4,000.00

websql use select in to get rows from an array

in websql we can request a certain row like this:
tx.executeSql('SELECT * FROM tblSettings where id = ?', [id], function(tx, rs){
// do stuff with the resultset.
},
function errorHandler(tx, e){
// do something upon error.
console.warn('SQL Error: ', e);
});
however, I know regular SQL and figured i should be able to request
var arr = [1, 2, 3];
tx.executeSql('SELECT * FROM tblSettings where id in (?)', [arr], function(tx, rs){
// do stuff with the resultset.
},
function errorHandler(tx, e){
// do something upon error.
console.warn('SQL Error: ', e);
});
but that gives us no results, the result is always empty. if i would remove the [arr] into arr, then the sql would get a variable amount of parameters, so i figured it should be [arr]. otherwise it would require us to add a dynamic amount of question marks (as many as there are id's in the array).
so can anyone see what i'm doing wrong?
aparently, there is no other solution, than to manually add a question mark for every item in your array.
this is actually in the specs on w3.org
var q = "";
for each (var i in labels)
q += (q == "" ? "" : ", ") + "?";
// later to be used as such:
t.executeSql('SELECT id FROM docs WHERE label IN (' + q + ')', labels, function (t, d) {
// do stuff with result...
});
more info here: http://www.w3.org/TR/webdatabase/#introduction (at the end of the introduction)
however, at the moment i created a helper function that creates such a string for me
might be better than the above, might not, i haven't done any performance testing.
this is what i use now
var createParamString = function(arr){
return _(arr).map(function(){ return "?"; }).join(',');
}
// when called like this:
createparamString([1,2,3,4,5]); // >> returns ?,?,?,?,?
this however makes use of the underscore.js library we have in our project.
Good answer. It was interesting to read an explanation in the official documentation.
I see this question was answered in 2012. I tried it in Google 37 exactly as it is recommened and this is what I got.
Data on input: (I outlined them with the black pencil)
Chrome complains:
So it accepts as many question signs as many input parameters are given. (Let us pay attention that although array is passed it's treated as one parameter)
Eventually I came up to this solution:
var activeItemIds = [1,2,3];
var q = "";
for (var i=0; i< activeItemIds.length; i++) {
q += '"' + activeItemIds[i] + '", ';
}
q= q.substring(0, q.length - 2);
var query = 'SELECT "id" FROM "products" WHERE "id" IN (' + q + ')';
_db.transaction(function (tx) {
tx.executeSql(query, [], function (tx, results1) {
console.log(results1);
debugger;
}, function (a, b) {
console.warn(a);
console.warn(b);
})
})