Split and validate text that contains brackets, commas and integers - validation

How can i split text which contains only brackets, commas and 3 integers. For example:
{5,40,30}
I also want to validate that it looks like above.

Try this using regex.
var testString = "12,23,{23,23},23,{51,22,345}{{]}1123,{12,12,232,123}{{33,33,33}}";
var regex = new Regex(#"{\d+,\d+,\d+}");
var matches = regex.Matches(testString);
The output of the above test string after match is
{51,22,345} and {33,33,33}

Here's a non regex solution using string methods and LINQ which i prefer:
string text = "{5,40,30}";
bool valid = text.StartsWith("{") && text.EndsWith("}");
int[] integers = {};
if (valid)
{
integers = text.Trim('{', '}').Split(',')
.Select(s => s.TryGetInt32())
.Where(nullInt => nullInt.HasValue)
.Select(nullInt => nullInt.Value)
.ToArray();
valid = integers.Length == 3;
}
using this handy extension method that i use in LINQ queries to get a Nullabel<int> from a string, so similar to int.TryParse but with an int?.
public static int? TryGetInt32(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}

Related

Compare two comma separated strings and get count of intersecting values

What is the best code for comparing 2 comma separated strings and retrieving values that intersect? For instance lets say I have string "a,b,c" and the target string "x,b,y", I need result saying there is 1 occurrence.
As suggested here One way of doing this is
public static bool UserCanAccessThisPage(string userAccessGroups,
string pageItemAccessGroups)
{
return userAccessGroups.Split(',')
.Select(s => s.Trim())
.Contains(pageItemAccessGroups);
}
But this will only check the match but I do also need occurrences. Any suggestions please
Use Enumerable.Intersect to get intersection of two sequences:
var occurrences =
userAccessGroups.Split(',').Select(s => s.Trim())
.Intersect(pageItemAccessGroups.Split(',').Select(s => s.Trim()));
Checking if occurrences exist:
bool exist = occurrences.Any();
Getting occurrences count:
int count = occurrences.Count();
To make code more readable you can store groups in local variables:
// this can be ordinal named method
Func<string, IEnumerable<string>> parse =
csv => csv.Split(',').Select(s => s.Trim());
var userGroups = parse(userAccessGroups);
var pateItemGroups = parse(pageItemAccessGroups);
var occurrences = userGroups.Intersect(pageItemGroups);

Comma delimited value Entity Framework in contains Statement

I have LINQ statement that has a comma delimited value.
I want to see if my Field matches any of the comma delimited values.
public string IdentifyProductSKU(string Serial)
{
int Len = Serial.Length;
var Split = from ModelSplitter in entities.Models
select ModelSplitter.m_validationMask.Split(',');
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
select ModelI.m_name).SingleOrDefault();
return Product;
}
To explain the code: Every Model has got multiple identifying properties for eg. XX1,XX5,XX7 is all the same product. Now when I pass in a serial number I want to Identify the product based on the validation mask. For eg: XX511122441141 is ProductA and YY123414124 is ProductC. I Just want to split the in this query so in this line:
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
I want to Split the Validation mask To see if the serial contains any of the validation mask characters. Does this make sense?
This is how you split values into a list
var split = context.Packs.Select(u => u.m_validationMask).ToList();
List<String[]> list=new List<String[]>();
foreach (var name in split)
{
String[] str = name.Split(',');
list.Add(str);
}
Now I need to know how I can use that list in my Final EF Query:
int Len = Serial.Length;
var split = entities.Models.Select(u => u.m_validationMask).ToList();
List<String[]> list = new List<String[]>();
foreach (var name in split)
{
String[] str = name.Split(',');
list.Add(str);
}
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
list.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
select ModelI.m_name).SingleOrDefault();
return Product;
I don't fully understand what you mean or what you are trying to do. But...
If your ModelSplitter.m_malicationMask can indead be split as you had demonstrated, then Split is a List then. What I don't understand is if you are trying to match the entire product A, or just the first three characters, you can modifiy your query
var Product = (from ModelI in entities.Models
where ModelI.m_validation == 0 &&
ModelI.m_validationLength == Len &&
ModelI.m_validationMask.Contains(Serial.Substring(ModelI.m_validationStart, ModelI.m_validationEnd))
let productId = ModelI.m_name.Substring(0, 3)
where split.Contains(productId)
select ModelI.m_name).SingleOrDefault();
Product should now be null if it does not match or an acutal product if it does.

try parse in linq

Hi I have a linq query as below
var perChange = (from data in globalDS.Tables[0].AsEnumerable().AsParallel()
select data.Field<double>("PercentChange")).ToList();
Now the dataset globalDS contains null as well as varchar values in them. So there is an obvious type cast error that is generated. Is there a way to try.Parse the value in "Percentage Change" column and select only the valid fields.
DataRow.Field supports nullable types:
List<double> result = globalDS.Tables[0].AsEnumerable().AsParallel()
.Where(r => r.Field<double?>("PercentChange").HasValue)
.Select(r => r.Field<double?>("PercentChange").Value)
.ToList();
Edit: Since you have mentioned that the field contains strings instead of doubles:
List<double> result = globalDS.Tables[0].AsEnumerable().AsParallel()
.Select(r => r.Field<string>("PercentChange").TryGetDouble())
.Where(nullDouble => nullDouble.HasValue)
.Select(nullDouble => nullDouble.Value)
.ToList();
I've used this extension to try-parse a string to double? which is safer than parsing "on the fly" into the local variable, especially with AsParallel:
public static Double? TryGetDouble(this string item, IFormatProvider formatProvider = null)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
Double d = 0d;
bool success = Double.TryParse(item, NumberStyles.Any, formatProvider, out d);
if (success)
return d;
else
return null;
}
How about this:
double temp;
var perChange = (
from data in globalDS.Tables[0].AsEnumerable().AsParallel()
where !data.IsNull("PercentChange")
&& double.TryParse(data.Field<string>("PercentChange"), out temp)
select double.Parse(data.Field<string>("PercentChange"))
).ToList();
Try a select using a where clause in which you check the type. This would be something like: where x != null && TypeOf(x) == double

Linq query to find non-numeric items in list?

Suppose I have the following list:
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
Is there some sort of query I can write in Linq that will return to me only the numeric items, i.e. the 1st, 2nd, and 4th items from the list?
-R.
strings.Where(s => { double ignored; return double.TryParse(s, out ignored); })
This will return all the strings that are parseable as doubles as strings. If you want them as numbers (which makes more sense), you could write an extension method:
public static IEnumerable<double> GetDoubles(this IEnumerable<string> strings)
{
foreach (var s in strings)
{
double result;
if (double.TryParse(s, out result))
yield return result;
}
}
Don't forget that double.TryParse() uses your current culture, so it will give different results on different computers. If you don't want that, use double.TryParse(s, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result).
Try this:
double dummy = 0;
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
var numbers = strings.Where(a=>double.TryParse(a, out dummy));
You could use a simple predicate to examine each string, like so:
var strings = new List<string>();
strings.Add("1");
strings.Add("12.456");
strings.Add("Foobar");
strings.Add("0.56");
strings.Add("zero");
var nums = strings.Where( s => s.ToCharArray().All( n => Char.IsNumber( n ) || n == '.' ) );

Reading Text Files with LINQ

I have a file that I want to read into an array.
string[] allLines = File.ReadAllLines(#"path to file");
I know that I can iterate through the array and find each line that contains a pattern and display the line number and the line itself.
My question is:
Is it possible to do the same thing with LINQ?
Well yes - using the Select() overload that takes an index we can do this by projecting to an anonymous type that contains the line itself as well as its line number:
var targetLines = File.ReadAllLines(#"foo.txt")
.Select((x, i) => new { Line = x, LineNumber = i })
.Where( x => x.Line.Contains("pattern"))
.ToList();
foreach (var line in targetLines)
{
Console.WriteLine("{0} : {1}", line.LineNumber, line.Line);
}
Since the console output is a side effect it should be separate from the LINQ query itself.
Using LINQ is possible. However, since you want the line number as well, the code will likely be more readable by iterating yourself:
const string pattern = "foo";
for (int lineNumber = 1; lineNumber <= allLines.Length; lineNumber++)
{
if (allLines[lineNumber-1].Contains(pattern))
{
Console.WriteLine("{0}. {1}", lineNumber, allLines[i]);
}
}
something like this should work
var result = from line in File.ReadAllLines(#"path")
where line.Substring(0,1) == "a" // put your criteria here
select line

Resources