Set a different variable depending on bool expression in Dart - flutter

In Dart we might want to set a variable to some fixed value, but which variable we set may depend on some bool expression. For example
String value = 'Hello World!';
bool sendToFirst = false;
String first = '';
String second = '';
if (sendToFirst){
first = value;
else {
second = value;
}
This block would do what you want, but is there a more concise way of doing this? Something like
(sendToFirst ? first : second) = value;
But of course this does not work.

There is a way to simplify if statements: Ternary expressions.
Following your example you have to code:
sendToFirst ? first = value : second = value
In the end you are just replacing the keywords with syntactic sugar, where the ? replaces the "if bool is true"-part, followed by a condition that should be executed (the body of the condition) and the colon : for the else-part, again, followed by a body.
FYI: You can mark value final, if you are not planning to re-asign a new value to it.

Related

String transformation for subject course code for Dart/Flutter

For interaction with an API, I need to pass the course code in <string><space><number> format. For example, MCTE 2333, CCUB 3621, BTE 1021.
Yes, the text part can be 3 or 4 letters.
Most users enter the code without the space, eg: MCTE2333. But that causes error to the API. So how can I add a space between string and numbers so that it follows the correct format.
You can achieve the desired behaviour by using regular expressions:
void main() {
String a = "MCTE2333";
String aStr = a.replaceAll(RegExp(r'[^0-9]'), ''); //extract the number
String bStr = a.replaceAll(RegExp(r'[^A-Za-z]'), ''); //extract the character
print("$bStr $aStr"); //MCTE 2333
}
Note: This will produce the same result, regardless of how many whitespaces your user enters between the characters and numbers.
Try this.You have to give two texfields. One is for name i.e; MCTE and one is for numbers i.e; 1021. (for this textfield you have to change keyboard type only number).
After that you can join those string with space between them and send to your DB.
It's just like hack but it will work.
Scrolling down the course codes list, I noticed some unusual formatting.
Example: TQB 1001E, TQB 1001E etc. (With extra letter at the end)
So, this special format doesn't work with #Jahidul Islam's answer. However, inspired by his answer, I manage to come up with this logic:
var code = "TQB2001M";
var i = course.indexOf(RegExp(r'[^A-Za-z]')); // get the index
var j = course.substring(0, i); // extract the first half
var k = course.substring(i).trim(); // extract the others
var formatted = '$j $k'.toUpperCase(); // combine & capitalize
print(formatted); // TQB 1011M
Works with other formats too. Check out the DartPad here.
Here is the entire logic you need (also works for multiple whitespaces!):
void main() {
String courseCode= "MMM 111";
String parsedCourseCode = "";
if (courseCode.contains(" ")) {
final ensureSingleWhitespace = RegExp(r"(?! )\s+| \s+");
parsedCourseCode = courseCode.split(ensureSingleWhitespace).join(" ");
} else {
final r1 = RegExp(r'[0-9]', caseSensitive: false);
final r2 = RegExp(r'[a-z]', caseSensitive: false);
final letters = courseCode.split(r1);
final numbers = courseCode.split(r2);
parsedCourseCode = "${letters[0].trim()} ${numbers.last}";
}
print(parsedCourseCode);
}
Play around with the input value (courseCode) to test it - also use dart pad if you want. You just have to add this logic to your input value, before submitting / handling the input form of your user :)

Reliably Extracting String In Flutter List Every Time

So I have a quite interesting exercise I've been trying to solve for a while now, but haven't come up with a reliable solution, so I thought you guys could help me out. I have this String that is composed of few random custom parts, for example:
"William\nWilliam description here...\n$170.00 usd") + Uuid().v4();
I need to extract the part after '$' and '.', in this case 170, but it can be any number between.
UPDATE
as I said in the last comment, if I wanted to do it in a function (find the price only), it could go something like this:
deleteSumItem(item) {
final regEx = RegExp(r'\$\d+(?:\.\d+)?');
const textToSearch = r'item';
final priceValueMatch = regEx.firstMatch(textToSearch);
print(priceValueMatch.group(0));
_totalPrice.remove(priceValueMatch);
_counter = _counter - priceValueMatch; //getting error here to convert to num
//but int.parse won't work either, then I get the String error
//RegExp can't be assigned to paremeter String
}
Also, this function returns null for regex, so there is some mistake I'm making, any thoughts?
deleteSumItem(item) {
final regEx = RegExp(r'\1\d+(?:\.\d+)?');
final priceValueMatch = regEx.firstMatch(r'item');
print('THIS IS REGEX: $priceValueMatch');} //priceValueMatch returns null
fix
deleteSumItem(item) {
RegExp regExp = RegExp(r'\^(\d+)\^');
String input = item;
String match = regExp.firstMatch("r" + '"' + input + '"').group(1);
print('Match: $match');
int number = int.parse(match);
print('Number: $number');
_totalPrice.remove(number);
_counter = _counter - number;}
Assuming you can answer 'yes' to the questions in my above comment, you can simply use regular expressions to find the price value in your string:
final regEx = RegExp(r'\$\d+(?:\.\d+)?');
const textToSearch = r'William\nWilliam description here...\n$170.00 cm';
final priceValueMatch = regEx.firstMatch(textToSearch);
print(priceValueMatch.group(0)); // this will print $170.00
The regular expression is looking for a dollar sign \$ followed by 1 or more digits d+ followed by optional decimal point and optional digits behind that decimal (?:\.\d+)?.
This actually ignores a lot of the questions in my above comment. This simply looks for a price value preceded by a dollar sign within the string you give it.
Here is another approach based on your comments. This is assuming the new line characters will always exist
const textToSearch = 'William\nWilliam description here...\n170.00 cm';
final lines = textToSearch.split('\n'); // Split on new line character
// If your template is always the same,
// then your number will be at the start of line 3:
print(lines[2]); // Will print: 170.00 cm
// If you want just your 170 value then:
final regEx = RegExp(r'\d+');
final priceValueMatch = regEx.firstMatch(lines[2]);
final priceInt = int.parse(priceValueMatch.group(0));
print(priceInt); // Will print: 170

empty form text filed

I'm using a FormTextField in a Flutter app
To update a certain column value, the user types in the FormTextField, otherwise leaves the field empty.
I tried this code, but it was adding a null value to the column, deleting the existing value. I'm not happy with this behavior.
String _getProd5Name() {
if ((_prod5Controller.text).isNotEmpty == true) {
_prod5String = _prod5Controller.text;
}
return _prod5String;
}
Is there a way to do it?
I found similar questions, but they are relevant to other languages and their solutions don't solve my case.
String _getProd5Name() {
// Actually you don't have to make it private
// since this is a local variable inside a function
String _prod5String = variableContainingInitialValue;
if (_prod5Controller.text.isNotEmpty) {
_prod5String = _prod5Controller.text;
}
return _prod5String;
}
Here is my advice, since I love wrapping everything on 1 line. You can change the "" part with your result expectation. It's the same with your logic but it's shorter and instead of returning null I make it returning the empty string "". And also (_prod5Controller.text).isNotEmpty == true you can just shorten it to (_prod5Controller.text).isNotEmpty because .isNotEmpty always returning boolean true/false and if-else consuming boolean
String _getProd5Name() {
return ((_prod5Controller.text).isNotEmpty) ? _prod5String = _prod5Controller.text : "";
}

Mirth String Handling

I'm using the code below to try and strip the file extension off the incoming file and replace it with "ACK";
Can't use .lastIndexOf as it's not available in Rhino.
var _filename = String(sourceMap.get('originalFilename'));
pos = -1;
var search = ".";
for(var i = 0; i < _filename.length - search.length; i++) {
if (_filename.substr(i, search.length) == search) {
pos = i;
}
}
logger.info('_pos:' + _pos);
Every time I get a pos value of -1
i.e. Last full stop position not found.
BUT if I hardcode the filename in as "2020049.259317052.HC.P.F3M147-G" it works perfectly.
Is it something to do with the sourceMap.get('originalFilename') supplying a non-string or different
character set ?
This was tested on mirth 3.5. Rhino does, in fact, have String.prototype.lastIndexOf for all mirth versions going back to at least mirth 3.0. You were correctly converting the java string from the sourceMap to a javascript string, however, it is not necessary in this case.
Java strings share String.prototype methods as long as there is not a conflict in method name. Java strings themselves have a lastIndexOf method, so that is the one being called in my answer. The java string is able to then borrow the slice method from javascript seamlessly. The javascript method returns a javascript string.
If for some reason the filename starts with a . and doesn't contain any others, this won't leave you with a blank filename.
var filename = $('originalFilename');
var index = filename.lastIndexOf('.');
if (index > 0) filename = filename.slice(0, index);
logger.info('filename: ' + filename);
That being said, I'm not sure why your original code wasn't working. When I replaced the first line with
var originalFilename = new java.lang.String('2020049.259317052.HC.P.F3M147-G');
var _filename = String(originalFilename);
It gave me the correct pos value of 22.
New Answer
After reviewing and testing what agermano said he is correct.
In your sample code you are setting pos = i but logging _pos
New answer var newFilename = _filename.slice(0, _filename.lastIndexOf('.'))
Older Answer
First, you are mixing JavaScript types and Java types.
var _filename = String(sourceMap.get('originalFilename'));
Instead, do
var _filename = '' + sourceMap.get('originalFilename');
This will cause a type conversion from Java String to JS string.
Secondly, there is an easier way to do what you are trying to do.
var _filenameArr = ('' + sourceMap.get('originalFilename')).split('.');
_filenameArr.pop() // throw away last item
var _filename = _filenameArr.join('.') // rejoin the array with out the last item
logger.info('_filename:' + _filename)

Dynamically formed http request

I need to send get request like this to my api:
http://test.example.com/api/activity/search?word={word}&age={age}&free={free}
and then show this activities in my page with *ngFor, but when user fill inputs, i need to dynamically insert values in unnecessary arguments of this.
What i already done:
//activity.service.ts :
searchActivities(word?: any, age?: any, free?: any) {
let w, a, f;
//contat values from forms here
w = word ? `word=${word}` : '';
a = age ? `age=${age}` : '';
f = free ? `free=${free}` : '';
return this.http.get(`http://test.example.com/api/activity/search?${w}${a}${f}`);
}
as you noticed, i miss ampersands here, and it works only with one input, for example when user wants to see all free football activities, he can't.
In my component i have this:
activities = [];
args: any[] = [null, null, null]; //array for values
//funtction attached to input's events
setArgument(index, value) {
this.args[index] = value; //fills array with values from inputs
this.activityService
// spread operator gives error in typescript for some reason, so i decided to put arguments this way
.searchActivities(this.args[0], this.args[1], this.args[2])
.subscribe((data: Response) => this.activities = data.json());
}
example of inputs:
<md-checkbox (click)="setArgument(5, !IsFree)" [(ngModel)]="IsFree" name="free">Free</md-checkbox>
<md-input-container>
<input (focusout)="setArgument(0, word)" [(ngModel)]="word" name="word" mdInput placeholder="Search word">
</md-input-container>
I hope you understood what i'm trying to do, i'm novice at programming and maybe i do it completely bad way. Please advice how can i deal with ampersands, and maybe simplify or rewrite this code somehow
A good solution to your ampersand problem would be Array.prototype.join
So you might add code similar to the following:
w = word ? `word=${word}` : '';
a = age ? `age=${age}` : '';
f = free ? `free=${free}` : '';
q = [w, a, f].filter(function(x) { return x !== '' }).join('&');
return this.http.get(`http://test.example.com/api/activity/search?${q}`);
So you create an array containing all of your query strings, filter out the ones that are empty, and the join together into a string separated with ampersand characters.