I am trying to compare an input value to a list of items in Dart language, however, it does not seem to work.
Method:
String validateStoreNumber(String value) {
List<String> storeList = ['55', '56', '88'];
// String patttern = r'(^[a-zA-Z ]*$)';
RegExp regExp = new RegExp(r'^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$');
if (value.length == 0) {
return "car number is required";
} else if (!regExp.hasMatch(value)) {
return "Accepts only numbers";
} else if (value.length != 2){
return "car number must have 2 digits";
} else if (value != storeList.contains(value)){
return "Not our model";
}
return null;
}
This line...
else if (value != storeList.contains(value))
Is the problem. The left side "value" is a string, and the right side "contains" is a boolean. You are comparing a string to a boolean.
I think you want this...
else if (!storeList.contains(value))
Related
In Dart the trim(), trimLeft() and trimRight() string methods do not take a parameter to specify unwanted non-whitespace characters.
What is the best way to trim a specific character from the ends of a string in Dart?
I am using this for now, but it feels hard to remember and not very generic:
final trailing = RegExp(r"/+$");
final trimmed = "test///".replaceAll(trailing, "");
assert(trimmed == "test");
There is no specific functionality to trim non-whitespace from the end of a string.
Your RegExp based approach is reasonable, but can be dangerous when the character you want to remove is meaningful in a RegExp.
I'd just make my own function:
String removeTrailing(String pattern, String from) {
if (pattern.isEmpty) return from;
var i = from.length;
while (from.startsWith(pattern, i - pattern.length)) i -= pattern.length;
return from.substring(0, i);
}
Then you can use it as:
final trimmed = removeTrailing("/", "test///")
assert(trimmed == "test");
The corresponding trimLeading function would be:
String trimLeading(String pattern, String from) {
if (pattern.isEmpty) return from;
var i = 0;
while (from.startsWith(pattern, i)) i += pattern.length;
return from.substring(i);
}
Since the existing answer by lrn has a lot of problems - including infinite loop scenarios - I thought I'd post my version.
String trimLeft(String from, String pattern){
if( (from??'').isEmpty || (pattern??'').isEmpty || pattern.length>from.length ) return from;
while( from.startsWith(pattern) ){
from = from.substring(pattern.length);
}
return from;
}
String trimRight(String from, String pattern){
if( (from??'').isEmpty || (pattern??'').isEmpty || pattern.length>from.length ) return from;
while( from.endsWith(pattern) ){
from = from.substring(0, from.length-pattern.length);
}
return from;
}
String trim(String from, String pattern){
return trimLeft(trimRight(from, pattern), pattern);
}
To trim all trailing/right characters by specified characters, use the method:
class StringUtil {
static String trimLastCharacters(String srcStr, String pattern) {
if (srcStr.length > 0) {
if (srcStr.endsWith(pattern)) {
final v = srcStr.substring(0, srcStr.length - 1 - pattern.length);
return trimLastCharacters(v, pattern);
}
return srcStr;
}
return srcStr;
}
}
For example, you want to remove all 0 behind the decimals
$23.67890000
then, invoke the method
StringUtil.trimLastCharacters("$23.67890000", "0")
finally, got the output:
$23.6789
Is there a better alternative then coding this:
String reps = status != null && status.sets != null && status.sets[index].reps != null ? status.sets[index].reps.toString() : '-';
I could also do this:
String reps;
try {
reps = hasImprovedReps ? currentReps : status.sets[index].reps.toString();
} catch (e) {
reps = '-';
}
But this way it's not one line and it's not a condition so I could use it in a Text()constructor.
You can use ?. and ?? operators:
String reps = status?.sets?.elementAt(index)?.reps?.toString() ?? '-'
I am using eeplus to create an excel spreadsheet, like this
using (var pck = new ExcelPackage())
{
var ws = pck.Workbook.Worksheets.Add("Customers");
ws.Cells["A1"].LoadFromCollection(customers, PrintHeaders: true);
var ms = new System.IO.MemoryStream();
pck.SaveAs(ms);
ms.WriteTo(Response.OutputStream);
}
The customer class has properties like
[DisplayName("Customer creation date")]
public DateTime Created { get; set; }
DisplayName seems to get honored, so the topmost line will read Customer creation date but the cell contents show up as 43257,41667.
What I would really like to have is cells that has the format 2018-04-05.
Can I do that will data annotations? I tried both
[DisplayName("Customer creation date")]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime Created { get; set; }
and
[DisplayName("Customer creation date")]
[DataType(DataType.Date)]
public DateTime Created { get; set; }
but the cell contents remains the same.
No, EPPlus doesnot format your data according to data annotations.
It formats date as integers, so you should specify the column you wish to format as
ws.Column(colPosition+1).Style.Number.Format="yyyy-mm-dd";
You can find details here:
https://github.com/JanKallman/EPPlus/wiki/Formatting-and-styling
https://codereview.stackexchange.com/questions/139569/ensuring-specific-columns-in-an-excelworksheet-format-as-shortdate
EPPlus always changed column name while updating into excel based upon DisplayName Attribute else if there is no DisplayName Attribute is set, then it will Find "_" (underscore) character & replace it with " " (Space) Character in the column name, Due to which we cannot easily find PropertyInfo with help of column name to format the column as per our need.
Here is the simple & quickest solution to format column based upon indexing the PropertyInfo
PropertyInfo[] props = typeof(T).GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < props.Length; i++)
{
Type t = props[i].PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(i + 1).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(i + 1).Style.Numberformat.Format = "HH:mm:ss";
}
I have another solution if you need to format columns based upon column names.
void ApplyDateTimeFormatting<T>(ExcelWorksheet ws, IEnumerable<T> data)
{
if (data.Count() == 0)
return;
Type type = data.First().GetType();
for (int c = 1; c <= toColumns; c++)
{
string column = ws.Cells[1, c].Text;
var t = type.GetPropertyWithDisplayName<T>(column).PropertyType;
if (t == typeof(DateTime) || t == typeof(DateTime?))
ws.Column(c).Style.Numberformat.Format = "dd-MMM-yyyy HH:mm:ss";
else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
ws.Column(c).Style.Numberformat.Format = "HH:mm:ss";
}
}
PropertyInfo GetPropertyFromDisplayName(Type type, string DisplayName)
{
MemberInfo[] members = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var member in members)
{
DisplayNameAttribute displayNameAttribute = member
.GetCustomAttributes(typeof(DisplayNameAttribute), inherit: false)
.FirstOrDefault() as DisplayNameAttribute;
string text = ((displayNameAttribute == null) ? member.Name.Replace('_', ' ') :
displayNameAttribute.DisplayName);
if (text == DisplayName)
return type.GetProperty(member.Name);
}
return null;
}
I solved it as follows, so I just load the model and change as per my model if it is int or datetime
var li = typeof(Model).GetProperties().ToArray();
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Sheet1");
var i = 0;
foreach (var c in li)
{
i++;
if(c.PropertyType.Name == typeof(DateTime).Name || c.PropertyType.Name == typeof(DateTime?).Name)
workSheet.Column(i).Style.Numberformat.Format = DateTimeFormatInfo.CurrentInfo.ShortDatePattern; ;
if (c.PropertyType.Name == typeof(int).Name || c.PropertyType.Name == typeof(int?).Name)
workSheet.Column(i).Style.Numberformat.Format = "0";
}
}
I am trying to do something that would logically look like this:
if text == "" || let i = Int(text) where i < 2 {
// do something; don't care about the value of i
}
Of course this isn't a valid condition -- what would the value of i be if text == "" is the part that holds? But, since I'm only interested in the value of i inside the where clause, I was hoping there is a nice way of achieving the same effect, namely executing the same closure if either condition holds. My current solution is to extract the closure and call it from two separate if blocks, but that's pretty hairy-looking.
The equivalent to your code example would be:
if text == "" || Int(text) ?? 2 < 2 {
print("valid")
// do your previous "something
} else {
print("invalid")
}
which yields
"" -> valid
"1" -> valid
"2" -> invalid
"abc" -> invalid
If you're doing this kind of comparison regularly, you could create your own operator in order to compare an optional with a given closure representing your condition for success. If the unwrapped value meets the condition, it'll return true – else false.
For example:
infix operator ?& {precedence 130 }
func ?&<T>(lhs: T?, #noescape rhs:(T)->Bool) -> Bool {
return lhs != nil ? rhs(lhs!) : false
}
...
if text == "" || Int(text) ?& {$0 < 2} {
print("valid")
} else {
print("invalid")
}
You could also overload the existing < operator to do this, but this may impact already existing code that relies on nil being less than a non-optional value.
func <<T:Comparable>(lhs: T?, rhs:T) -> Bool {
return lhs != nil ? (lhs! < rhs) : false
}
...
if text == "" || Int(text) < 2 {
print("valid")
} else {
print("invalid")
}
Perhaps a more "Swifty" way to handle optional values is with map. Essentially, mapping an optional value gives you an unwrapped value in your closure, which you can then modify to return what you need. Outside the closure, you will receive either the modified value, or nil if the original optional was nil.
let optInt: Int? = 1 // or nil
let incremented: Int? = optInt.map { $0 + 1 }
// If optInt isn't nil, its incremented value is returned by map.
// If it is nil, map just returns nil.
So to solve my problem, I could do:
if text == "" || Int(text).map({$0 < 2}) ?? false {
// If text has an Int value, the map closure will return
// whether that value is less than 2.
// Else, map will return nil, which we coalesce to false.
}
What I'm trying to do is to make it where the user can type in a textbox and then click on a button and it will search the richtextbox for what they are looking for and if it found something it will change the label.
(Instances)
`
Button = btn_Search
Textbox = InputBox
RichTextBox = rtb
Label = Results`
Use this method, to find any Text inside your RichTextBox.
public int FindMyText(string searchText, int searchStart, int searchEnd)
{
// Initialize the return value to false by default.
int returnValue = -1;
// Ensure that a search string and a valid starting point are specified.
if (searchText.Length > 0 && searchStart >= 0)
{
// Ensure that a valid ending value is provided.
if (searchEnd > searchStart || searchEnd == -1)
{
// Obtain the location of the search string in richTextBox1.
int indexToText = richTextBox1.Find(searchText, searchStart, searchEnd, RichTextBoxFinds.MatchCase);
// Determine whether the text was found in richTextBox1.
if(indexToText >= 0)
{
// Return the index to the specified search text.
returnValue = indexToText;
}
}
}
return returnValue;
}
call this method like this:
var res= FindMyText("hello",0. richTextBox1.Text.Length);
now if res>-1, that means positive match, then you can set your labels i.e.
if(res>-1){
lbl1.Text = "hello found";
}
source here and here
Another method of searching text that is far more clean is as below,but first you need to add
System.Text.RegularExpressions namespace to your project;
private void SearchButton_Click(object sender, EventArgs e)
{
if (textBox1.TextLength >= 1)
{
string word = textBox1.Text;//The text you want to search.
Regex searchterm = new Regex(word);//A Regular Expression is most efficient way of working with text.
MatchCollection matches = searchterm.Matches(richTextBox1.Text);
if (matches.Count >= 1)
{
Results=matches.Count.ToString();//Your label to display match instances.
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
richTextBox1.DeselectAll();
foreach (Match match in matches)
{
richTextBox1.Select(match.Index, match.Length);
richTextBox1.SelectionBackColor = Color.Orange;
richTextBox1.DeselectAll();
}
}
}
}
This should do the job,furthermore if you want to specify additional search options,replace the line with Regex searchterm with anyone below,
Case Insensitive
Regex searchterm = new Regex(word,RegexOptions.IgnoreCase);
Whole Word Search
Regex searchterm = new Regex(#"\b"+word+"\b");
Case Insensitive and Whole Word Search
Regex searchterm = new Regex(#"\b"+word+"\b",RegexOptions.IgnoreCase);
and one more thing,Regex searches are case-sensitive by default.