DOORS DXL. How to put each word in a string into separate strings - ibm-doors

I want to put each word in a string into a separate string. So if my string has a list of words like, "John, Mary, Barbara" and the words are separate by a carriage return (not a comma as shown in the example), how do I put John into one string, Mary into another string and Barbara into a third string. The strings are not created so I will have to create them on the fly and that is ok. This is what I have tried:
for (n; n<100; n++){
s1 = s[n:n]
if(s1 == "\n") {
break
}
}
Since I want this separation to occur for every object (a specific column in a module) I will have to put whatever the correct code is into a loop like "for o in m do{ }.
Thank you for helping me.

Maybe these functions would help. However, you would have to get familiar with the Skip type (the DXL manual helps with that).
stringSplit() divides str into substrings based on a delimiter, returning an array (Skip type) of these substrings. If pattern is a String, then its contents are used as the delimiter when splitting str. If pattern is empty or null, the value of a single space is used. If pattern is a single space, str is split on whitespace, with leading whitespace and runs of contiguous whitespace characters ignored.
Skip stringSplit(string str, string pattern) {
if (null str) return null
if (null(pattern) || 0 == length(pattern))
pattern = " ";
Skip result = create;
int i = 0; // index for searching in str
int j = 0; // index counter for result array
bool found = true;
while (found) {
// find pattern
int pos = 0;
int len = 0;
found = findPlainText(str[i:], pattern, pos, len, true);
if (found) {
// insert into result
put(result, j++, str[i:i+pos-1]);
i += pos + len;
}
}
// append the rest after last found pattern
put(result, j, str[i:]);
return result;
}
You might prefer to remove the commas first since the last word is not followed by a comma.
stringWipe() returns a copy of str with all occurrences of characters in chars eliminated:
string stringWipe(string str, string chars) {
if (null str) return str
int lenStr = length str
if (lenStr == 0) return str
int lenChars = length(chars);
if (lenChars == 0) return str
Buffer buf = create
int i
for (i=0; i<lenStr; i++) {
char c = str[i]
bool skip = false
int j
for (j=0; j<lenChars; j++) {
if (c == chars[j]) {
skip = true
break
}
}
if (skip)
continue
buf += c
}
string result = stringOf(buf);
delete buf
return result
}

Related

How to create a function WordSplit(strArr) read the array of strings stored in strArr using dart

I have a simple exercise in Coderbyte, it just want to have a function that's WordSplit(strArr) read the array of strings stored in strArr, For example I have two elements like ["hellocat", "apple,bat,cat,goodbye,hello,yellow,why"]
I just want to to determine if the first element in the input can be split into two words, where both words exist in the dictionary that is provided in the second input.
For example: the first element can be split into two words: hello and cat because both of those words are in the dictionary.
So the program should return the two words that exist in the dictionary separated by a comma, as this result hello,cat .
I've made a recursive solution below. It checks if the string to be split starts with any word in the dictionary. If it exists, the function is called again using a substring with that first word removed.
This function only works up to the first word that isn't in the dictionary since you did not specify the expected behavior when the inputted word is not made up of words in the dictionary. You could make it throw an exception perhaps, but please specify your expectation.
void main() {
print(wordSplit(["hellocat", "apple,bat,cat,goodbye,hello,yellow,why"]));
//hello,cat
}
String wordSplit(List<String> arg) {
String wordToSplit = arg[0];
String dict = arg[1];
List<String> parsedDict = arg[1].split(',');
for(String word in parsedDict) {
if(wordToSplit.startsWith(word)) {
//If the substring would be empty, don't do more recursion
if(word.length == wordToSplit.length) {
return word;
}
return word + ',' + wordSplit([wordToSplit.substring(word.length), dict]);
}
}
return wordToSplit;
}
#include <bits/stdc++.h>
using namespace std;
vector<string> converToWords(string dict) {
vector<string> res;
string s = "";
int n = dict.length();
for(int i=0; i<n; i++) {
if(dict[i] == ',') {
res.push_back(s);
s = "";
}
else s += dict[i];
}
res.push_back(s);
s = "";
return res;
}
string solve(string str[]) {
string result = "";
string word = str[0], dict = str[1];
int n = word.length();
vector<string> vs = converToWords(dict);
unordered_set<string> ust;
for(auto it: vs) ust.insert(it);
// for(auto i=ust.begin(); i!=ust.end(); i++){
// cout<<*i<<endl;
// }
string s = "";
for(int i=0; i<n; i++) {
s += word[i];
// cout<<s<<endl;
string temp = word.substr(i+1, n-(i+1));
// cout<<temp<<endl;
if(ust.find(s) != ust.end() && ust.find(temp) != ust.end()) {
cout<<s<<endl;
cout<<temp<<endl;
result += s+","+temp;
break;
}
temp = "";
}
return result;
}
int main() {
string arr[2];
cin>>arr[0]>>arr[1];
cout << solve(arr);
return 0;
}

dxl findPlainText check does not match string

I have a subroutine that I pass a string value from a skip list. That value is compared to objects in a Doors File. But the comparison does not work.
Skip split (string s, string delim)
{
Skip skp = create
int i = 0
Regexp split = regexp "^(.*?)" delim "(.*)$"
while (split s)
{
string temp_s = s[match 2]
put(skp, i++, s[match 1] "")
s = temp_s
}
put(skp, i++, s "")
return skp
}
string getInfo( string inStr)
{
for currObj in currMod do
{
if ( findPlainText( ( currOBJ.SW_VRC ""), inStr, offsetFromFind, lengthFromFind, false ) )
{
print currOBJ.SW_VRC " matches " inStr "\n";
}
}
}
Skip newLst = split(modname, ",") // this just splits a string input into parameters separated by commas
string inputInfo;
find(newLst, 0, inputInfo)
getInfo(inputInfo)
Now this is a simplified version of what I am doing. But the findPlainText does not match anything. inputInfo is getting the correct string, I checked.
The part that really kills me is if I hardcode in the parameter
i.e. inStr = "21";
It works like it's supposed to.
Now I was assuming a string is a string. Is there a difference between a string from a skip list and a string that's quoted? Is there a hidden character?
What am I missing? Any insight you could provide would be welcome.
Thanks,
DevM
your snippet works, but I had to add some variables to make it work, and I don't have a split function at hand:
Skip split (string s, string delim)
{
Skip skp = create
int i = 0
Regexp split = regexp "^(.*?)" delim "(.*)$"
while (split s)
{
string temp_s = s[match 2]
put(skp, i++, s[match 1] "")
s = temp_s
}
put(skp, i++, s "")
return skp
}
string SW_VRC="Object Text"
Module currMod = current Module
string getInfo( string inStr)
{
int offsetFromFind, lengthFromFind
string resultString = ""
Object currObj
for currObj in currMod do
{
if ( findPlainText( ( currObj.SW_VRC ""), inStr, offsetFromFind, lengthFromFind, false ) )
{
print currObj.SW_VRC " matches " inStr "\n";
resultString = resultString "\n" currObj.SW_VRC ""
}
}
return resultString
}
string modname = "a,b,cc,ccc,d,e,f"
Skip newLst = split (modname,",")
string inputInfo= "";
find(newLst, 0, inputInfo)
getInfo(inputInfo)
Perhaps you removed too much information when preparing this post?
Or you don't have an entry with the key "0" in newLst? What happens if you start your function with
string inputInfo
inputInfo = "21"
getInfo (inputInfo)
?

Flutter/Dart: Split string by first occurrence

Is there a way to split a string by some symbol but only at first occurrence?
Example: date: '2019:04:01' should be split into date and '2019:04:01'
It could also look like this date:'2019:04:01' or this date : '2019:04:01' and should still be split into date and '2019:04:01'
string.split(':');
I tried using the split() method. But it doesn't have a limit attribute or something like that.
You were never going to be able to do all of that, including trimming whitespace, with the split command. You will have to do it yourself. Here's one way:
String s = "date : '2019:04:01'";
int idx = s.indexOf(":");
List parts = [s.substring(0,idx).trim(), s.substring(idx+1).trim()];
You can split the string, skip the first item of the list created and re-join them to a string.
In your case it would be something like:
var str = "date: '2019:04:01'";
var parts = str.split(':');
var prefix = parts[0].trim(); // prefix: "date"
var date = parts.sublist(1).join(':').trim(); // date: "'2019:04:01'"
The trim methods remove any unneccessary whitespaces around the first colon.
Just use the split method on the string. It accepts a delimiter/separator/pattern to split the text by. It returns a list of values separated by the provided delimiter/separator/pattern.
Usage:
const str = 'date: 2019:04:01';
final values = string.split(': '); // Notice the whitespace after colon
Output:
Inspired by python, I've wrote this utility function to support string split with an optionally maximum number of splits. Usage:
split("a=b=c", "="); // ["a", "b", "c"]
split("a=b=c", "=", max: 1); // ["a", "b=c"]
split("",""); // [""] (edge case where separator is empty)
split("a=", "="); // ["a", ""]
split("=", "="); // ["", ""]
split("date: '2019:04:01'", ":", max: 1) // ["date", " '2019:04:01'"] (as asked in question)
Define this function in your code:
List<String> split(String string, String separator, {int max = 0}) {
var result = List<String>();
if (separator.isEmpty) {
result.add(string);
return result;
}
while (true) {
var index = string.indexOf(separator, 0);
if (index == -1 || (max > 0 && result.length >= max)) {
result.add(string);
break;
}
result.add(string.substring(0, index));
string = string.substring(index + separator.length);
}
return result;
}
Online demo: https://dartpad.dev/e9a5a8a5ff803092c76a26d6721bfaf4
I found that very simple by removing the first item and "join" the rest of the List
String date = "date:'2019:04:01'";
List<String> dateParts = date.split(":");
List<String> wantedParts = [dateParts.removeAt(0),dateParts.join(":")];
Use RegExp
string.split(RegExp(r":\s*(?=')"));
Note the use of a raw string (a string prefixed with r)
\s* matches zero or more whitespace character
(?=') matches ' without including itself
You can use extensions and use this one for separating text for the RichText/TextSpan use cases:
extension StringExtension on String {
List<String> controlledSplit(
String separator, {
int max = 1,
bool includeSeparator = false,
}) {
String string = this;
List<String> result = [];
if (separator.isEmpty) {
result.add(string);
return result;
}
while (true) {
var index = string.indexOf(separator, 0);
print(index);
if (index == -1 || (max > 0 && result.length >= max)) {
result.add(string);
break;
}
result.add(string.substring(0, index));
if (includeSeparator) {
result.add(separator);
}
string = string.substring(index + separator.length);
}
return result;
}
}
Then you can just reference this as a method for any string through that extension:
void main() {
String mainString = 'Here was john and john was here';
print(mainString.controlledSplit('john', max:1, includeSeparator:true));
}
Just convert list to string and search
productModel.tagsList.toString().contains(filterText.toLowerCase())

How can I insert a space character in every upper case letter expect the first one at each element of string array in DXL script?

I would like to edit the elements of string array with DXL script which is used in for loop. The problem will be described in the following:
I would like to insert space in front of every upper case letter expect the first one and it would be applied for all lines in string array.
Example:
There is a string array:
AbcDefGhi
GhiDefAbc
DefGhiAbc
etc.
and finally I would like to see the result as:
Abc Def Ghi
Ghi Def Abc
Def Ghi Abc
etc.
Thanks in advance!
Derived straightly from the DXL manual..
Regexp upperChar = regexp2 "[A-Z]"
string s = "yoHelloUrban"
string sNew = ""
while (upperChar s) {
sNew = sNew s[ 0 : (start 0) - 1] " " s [match 0]
s = s[end 0 + 1:]
}
sNew = sNew s
print sNew
You might have to tweak around the fact that you do not want EVERY capital letter to be replaced with , only those that are not at the beginning of your string.
Here's a solution written as a function that you can just drop into your code. It processes an input string character by character. Always outputs the first character as-is, then inserts a space before any subsequent upper-case character.
For efficiency, if processing a large number of strings, or very large strings (or both!), the function could be modified to append to a buffer instead of a string, before finally returning a string.
string spaceOut(string sInput)
{
const int intA = 65 // DECIMAL 65 = ASCII 'A'
const int intZ = 90 // DECIMAL 90 = ASCII 'Z'
int intStrLength = length(sInput)
int iCharCounter = 0
string sReturn = ""
sReturn = sReturn sInput[0] ""
for (iCharCounter = 1; iCharCounter < intStrLength; iCharCounter++)
{
if ((intOf(sInput[iCharCounter]) >= intA)&&(intOf(sInput[iCharCounter]) <= intZ))
{
sReturn = sReturn " " sInput[iCharCounter] ""
}
else
{
sReturn = sReturn sInput[iCharCounter] ""
}
}
return(sReturn)
}
print(spaceOut("AbcDefGHi"))

Genie how to return an array of unowned strings

how to return an array of unowned strings that all point to the same location in memory?
example:
init
var str = "ABC"
var unowned_string_array = repeat (str, 5)
def repeat (s: string, n: int): array of string
// code
and this array will contains 5 elements(same string "ABC"), all point to same location
The closest Vala code I could get is:
int main() {
var str = "ABC";
var unowned_string_array = repeat (str, 5);
return 0;
}
public (unowned string)[] repeat (string s, int n) {
var a = new (unowned string)[n];
for (var i = 0; i < n; i++)
// This sadly still duplicates the string,
// even though a should be an array of unowned strings
a[i] = s;
return a;
}
I'm not sure if the compiler understands the parenthesis here, it may think that I want to declare an unowned array of owned strings here ...
Update: It turns out the problem is that type inference will always create an owned variable (see nemequs comment).
There is even a bug report for this.
So this works just fine (no string duplication in the repeat function):
int main() {
var str = "ABC";
(unowned string)[] unowned_string_array = repeat (str, 5);
return 0;
}
public (unowned string)[] repeat (string s, int n) {
(unowned string)[] a = new (unowned string)[n];
for (var i = 0; i < n; i++)
// This sadly still duplicates the string,
// even though a should be an array of unowned strings
a[i] = s;
return a;
}
Which would be something like this in Genie:
[indent=4]
init
var str = "ABC"
unowned_string_array: array of (unowned string) = repeat (str, 5)
def repeat (s: string, n: int): array of (unowned string)
a: array of (unowned string) = new array of (unowned string)[n]
for var i = 1 to n
a[i] = s
return a
The Genie code has the additional problem of not compiling, due to the parser not being able to deduce what comes after the array of.
This seems to be a similar problem to what I already had with nested generic types.
I have reported this a Genie bug.

Resources