How to find last occurrence of a substring using Kusto Query Language? - azure-application-insights

Kusto Query Language provides IndexOf function (searches the first occurrence). The question is how to find the last occurrence of some substring.

I guess, the best you can do is (example on how to search for last "cde" in "abcdefabcdef"):
datatable (name:string, lookup:string)["abcdefabcdef", "cde"]
| project value = strlen(name) - indexof(reverse(name), reverse(lookup)) - strlen(lookup)

You can pass the result of countof to the occurence parameter of indexof:
let lastIndexof = (input:string, lookup: string) {
indexof(input, lookup, 0, -1, countof(input,lookup))
};
print lastIndexof("abcdefabcdef", "cde")

Related

Kamailio - get first occurrence value of a param in a string

I need to get the value of first tgrp param in this string using Kamailio :
$var(x) = <sip:xxxxxxxxx;tgrp=0001000;trunk-context=xx.xx.xx.xx#xx.xx.xx.xx:5060;transport=UDP;user=phone;tgrp=237>
I’m trying $var(y) = $(var(x){param.value,tgrp}); but it’s getting the last value of tgrp which is 237>.
Noting that first tgrp is not always in the second index , some other parameters can be added to the string.
How to get the value of first occurrence of tgrp param ?
param.value string operations designed to work with unique params names.
You can loop over all params using for loop and checking {param.name,index}
Try a solution based on xavp_params_explode():
https://kamailio.org/docs/modules/stable/modules/pv.html#pv.f.xavp_params_explode
Something like:
xavp_params_explode("$(var(x){s.unbracket})", "x");
xdbg("$xavp(x=>tgrp[0])"); # <- print the value of first parameter tgrp
The index [0] can be omitted, without it first value being returned, but if you want the second param value, then use [1] as index.

Xquery variable concat based on condition

I am trying to concat the value of an element based on certain condition, but unable to do so. What's wrong here?
For below given sample structure, I need to concat the value of CID based upon OutcomeCode code. Say if we have OutcomeCode as OC and PC, then we should display concatenated value of CId in a string variable.
<v4:ValidateResponse xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v4="http://service.com/v4">
<v4:Details>
<v4:Detail>
<v4:CId>001</v4:CId>
</v4:Detail>
<v4:OutcomeCode>FC</v4:OutcomeCode>
</v4:Details>
<v4:Details>
<v4:Detail>
<v4:CId>002</v4:CId>
</v4:Detail>
<v4:OutcomeCode>PC</v4:OutcomeCode>
</v4:Details>
<v4:Details>
<v4:Detail>
<v4:CId>003</v4:CId>
</v4:Detail>
<v4:OutcomeCode>OC</v4:OutcomeCode>
</v4:Details>
</v4:ValidateResponse>
Here is my transformation
as xs:string
{
for $Details in $ValidateResponse /*:Details
let $OutcomeCode := data($Details/*:OutcomeCode)
return
if (($OutcomeCode ='OC') or ($OutcomeCode='PC'))
then
contact('CID is-',data($Details/*:Detail/*:CId))
else
fn:data('Technical_Check')
};
I am unable to get concat values.
Expected result should be like: CID is- 002,003
as these 2 meet the OC and PC condition.
You could simplify this for loop and combine the criteria into a single XPath to select the CId from Details that have OutcomeCode of "OC" or "PC".
Then, use string-join() in order to produce a comma separated value.
Then, use concat() to produce a string with the prefix and the CSV value:
concat('CID is- ',
string-join(
$ValidateResponse/*:Details[*:OutcomeCode =('OC','PC')]/*:Detail/*:CId,
",")
)

Passing list of search string in contains in FilterExpression

Is there any way to pass a list of search strings in the contains() method of FilterExpression in DynamoDb?
Something like below:
search_str = ['value-1', 'value-2', 'value-3']
result = kb_table.scan(
FilterExpression="contains (title, :titleVal)",
ExpressionAttributeValues={ ":titleVal": search_str }
)
For now I can only think of looping through the list and scanning the table multiple times (as in below code), but I think it will be resource heavy.
for item in search_str:
result += kb_table.scan(
FilterExpression="contains (title, :titleVal)",
ExpressionAttributeValues={ ":titleVal": item }
)
Any suggestions.
For the above scenario, the CONTAINS should be used with OR condition. When you give array as input for CONTAINS, DynamoDB will check for the SET attribute ("SS", "NS", or "BS"). It doesn't looks for the sub-sequence on the string attribute.
If the target attribute of the comparison is of type String, then the
operator checks for a substring match. If the target attribute of the
comparison is of type Binary, then the operator looks for a
subsequence of the target that matches the input. If the target
attribute of the comparison is a set ("SS", "NS", or "BS"), then the
operator evaluates to true if it finds an exact match with any member
of the set.
Example:-
movies1 = "MyMovie"
movies2 = "Big New"
fe1 = Attr('title').contains(movies1)
fe2 = Attr('title').contains(movies2)
response = table.scan(
FilterExpression=fe1 or fe2
)
a little bit late but to allow people to find a solution i give here my method.
lets assume that in your DB you have a props called 'EMAIL you want to filter your scan on this EMAIL with a list of value. you can proceed as following.
list_of_elem=['mail1#mail.com','mail2#mail.com','mail3#mail.com']
#set an empty string to create your query
stringquery=""
# loop each element in your list
for index,value in enumerate(list_of_elem):
# add your query of contains with mail value
stringquery=stringquery+f"Attr('EMAIL').contains('{value }')"
# while your value is not the last element in list add the 'OR' operator
if index < len(list_of_elem)-1:
stringquery=stringquery+ ' | '
dynamodb = boto3.resource('dynamodb')
# Use eval of your query string to parse the string as filter expression
tableUser = dynamodb.Table('mytable')
tableUser.scan(
FilterExpression=eval(stringquery)
)

Find word (not containing substrings) in comma separated string

I'm using a linq query where i do something liike this:
viewModel.REGISTRATIONGRPS = (From a In db.TABLEA
Select New SubViewModel With {
.SOMEVALUE1 = a.SOMEVALUE1,
...
...
.SOMEVALUE2 = If(commaseparatedstring.Contains(a.SOMEVALUE1), True, False)
}).ToList()
Now my Problem is that this does'n search for words but for substrings so for example:
commaseparatedstring = "EWM,KI,KP"
SOMEVALUE1 = "EW"
It returns true because it's contained in EWM?
What i would need is to find words (not containing substrings) in the comma separated string!
Option 1: Regular Expressions
Regex.IsMatch(commaseparatedstring, #"\b" + Regex.Escape(a.SOMEVALUE1) + #"\b")
The \b parts are called "word boundaries" and tell the regex engine that you are looking for a "full word". The Regex.Escape(...) ensures that the regex engine will not try to interpret "special characters" in the text you are trying to match. For example, if you are trying to match "one+two", the Regex.Escape method will return "one\+two".
Also, be sure to include the System.Text.RegularExpressions at the top of your code file.
See Regex.IsMatch Method (String, String) on MSDN for more information.
Option 2: Split the String
You could also try splitting the string which would be a bit simpler, though probably less efficient.
commaseparatedstring.Split(new Char[] { ',' }).Contains( a.SOMEVALUE1 )
what about:
- separating the commaseparatedstring by comma
- calling equals() on each substring instead of contains() on whole thing?
.SOMEVALUE2 = If(commaseparatedstring.Split(',').Contains(a.SOMEVALUE1), True, False)

Substring with Multiple Arguments

I have a dropdownlist that has the value of two columns in it... One column is a number ranging from 5 characters long to 8 characters long then a space then the '|' character and another space, followed by a Description for the set of numbers.
An example:
12345678 | Description of Product
In order to pull the items for the dropdownlist into my database I need a to utilize a substring to pull the sequence of numbers out only.
Is it possible to write a substring to pull multiple character lengths? (Sometimes it may be 6 numbers, sometimes 5 numbers, sometimes 8, it would depend on what the user selected from the dropdownlist.)
Use a regular expression for this.
Assuming the number is at the start of the string, you can use the following:
^[0-9]+
Usage:
var theNumbers = RegEx.Match(myDropdownValue, "^[0-9]+").Value;
You could also use string.Split to get the parts separated by | if you know the first part is what you need and will always be numeric:
var theNumbers = myDropdownValue.Split("| ".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries)[0];
Either of these approaches will result in a string. You can use int.Parse on the result in order to get an integer from it.
This is how I would do it
string str = "12345678 | Description of Product";
int delimiter;
delimiter = str.IndexOf("|") - 1;
string ID =str.substring(0, delimiter);
string desc = str.substring(delimiter + 1, str.length - 1);
Try using a regex to pull out the first match of a sequence of numbers of any length. The regex will look something like "^\d+" - starts with any number of decimal digits.
Instead of using substring, you should use Split function.
var words = phrase.Split(new string[] {" | "},
StringSplitOptions.RemoveEmptyEntries);
var number = word[0];

Resources