I researched this and cannot figure out why ?! doesn't do a Not Equal in my code.
The code has this :
var policyOne = "C";
var policyTwo = "GF1";
var policyThree = "018"
string policyNumber = $"^(?!{Regex.Escape(policyOne)}){Regex.Escape(policyTwo)}{Regex.Escape(policyTwo)}$",
So while I have also tried ?!.* , I still cannot get it to recognize that the policyOne is NOT allowed to be "C"
All 3 of the variables are joined together in a sql linq where clause
I can provide more details if needed.
This is my code
string AnyStart = "XXXDEFGHI";
string AnythingMiddle = "ABCXXXGHI";
string AnyEnds = "ABCDEFZZZ";
List<string> Strings = new List<string>()
{
AnythingMiddle,
AnyStart,
AnyEnds
};
string hcdpPlnCvgCD = "ABC";
string HcdpPmtFctrCd = "DEF";
string hccCpmtFctrCd = "GHI";
var patterns = new string[]{
$"^(?!{Regex.Escape(hcdpPlnCvgCD)}){Regex.Escape(HcdpPmtFctrCd)}{Regex.Escape(hccCpmtFctrCd)}$",
$"^{Regex.Escape(hcdpPlnCvgCD)}(?!.*{Regex.Escape(HcdpPmtFctrCd)}){Regex.Escape(hccCpmtFctrCd)}$",
$"^{Regex.Escape(hcdpPlnCvgCD)}{Regex.Escape(HcdpPmtFctrCd)}(?!.*{Regex.Escape(hccCpmtFctrCd)})$",
};
var wildcards = new List<string>();
foreach (var pattern in patterns)
{
var matchResult = Strings.Where(s => Regex.IsMatch(s, pattern)).ToList();
matchResult.Dump();
}
wildcards.Dump();
I'm going to suggest a few things, first you should be evaluating the 3 different patterns individually. Second it seems like a plan has some logic behind it so I propose a Plan class. Then you can use Linq to find the plans you want.
public class Plan
{
public Plan(string planCode)
{
PlanCode = planCode;
Evaluate();
}
private const string _planCoverage= "^ABC";
private const string _planPaymentFactor= "DEF";
private const string _planCoPaymentFactor = "GHI$";
public string PlanCode { get; set; }
public bool IsCoverage { get; set; }
public bool IsPayment { get; set; }
public bool IsCoPay { get; set; }
private void Evaluate()
{
IsCoverage = Regex.IsMatch(PlanCode, _planCoverage);
IsPayment = Regex.IsMatch(PlanCode, _planPaymentFactor);
IsCoPay = Regex.IsMatch(PlanCode, _planCoPaymentFactor);
}
}
using this class the following code should accomplish what you're trying to do
string anyStart = "XXXDEFGHI";
string anyMiddle = "ABCXXXGHI";
string anyEnd = "ABCDEFZZZ";
List<Plan> plans = new List<Plan>(){
new Plan(anyStart),
new Plan(anyMiddle),
new Plan(anyEnd)
};
//what your first regex tried to accomplish
List<string> noCoveragePlans = plans
.Where(plan => !plan.IsCoverage && plan.IsPayment && plan.IsCoPay)
.Select(plan => plan.PlanCode)
.ToList();
//what your second regex tried to accomplish
List<string> noPaymentPlans = plans
.Where(plan => plan.IsCoverage && !plan.IsPayment && plan.IsCoPay)
.Select(plan => plan.PlanCode)
.ToList();
//what your third regex tried to accomplish
List<string> noCoPayPlans = plans
.Where(plan => plan.IsCoverage && plan.IsPayment && !plan.IsCoPay)
.Select(plan => plan.PlanCode)
.ToList();
Related
I have Department table values in EF model and one of the column has value has value values like DEPTName YEAR-EMPid 'ACCT 2020-012', 'SVC 2021-014', 'MRKT 2022-001' . How do I sort to get values in the below order in EF using LINQ. The prefix for department is sometimes 3 or 4
'MRKT 2022-001'
'SVC 2021-014'
'ACCT 2020-012'
Please advise.
var depPrefix ='XYZ "
var rs = qry.select(x=> new DeptDto { DeptId = x.DeptId , Dep = x.Dep, DeptEmp=x.Dep.SubString(0, x.Dep.Length - depPrefix.length)});
The above works well with prefix has only 3 dept abbreviation; but fails when more/less than 3.
Use IComparable
static void Main(string[] args)
{
string[] input = {"MRKT 2022-001", "SVC 2021-014", "ACCT 2020-012"};
var results = input.Select(x => new MyCompare(x)).OrderByDescending(x => x).Select(x => x.input).ToArray();
}
public class MyCompare : IComparable<MyCompare>
{
public string input { get; set; }
string prefix { get; set; }
int year { get; set; }
int suffix { get; set; }
const string pattern = #"^(?'prefix'[^\s]+)\s+(?'year'\d{4})-(?'suffix'.*)";
public MyCompare(string input)
{
this.input = input;
Match match = Regex.Match(input, pattern);
prefix = match.Groups["prefix"].Value;
year = int.Parse(match.Groups["year"].Value);
suffix = int.Parse(match.Groups["suffix"].Value);
}
public int CompareTo(MyCompare other)
{
if (this.year != other.year)
return this.year.CompareTo(other.year);
if (this.prefix != other.prefix)
return this.prefix.CompareTo(other.prefix);
return this.suffix.CompareTo(other.suffix);
}
}
I have a list of string that looks something like this:
var rawData = new List<string>(){ "EUR/USD;123" , "EUR/GBP;321", "BTC/USD;2321"};
I have the following structure:
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}
My goal is to have a list of the string data, splited on the ';' char and converted to a list of objects.
var processedData = new List<Data>();
// processedData[0] ( instrument = EUR/USD, positions = 123 )
// processedData[1] ( instrument = EUR/GBP, positions = 321)
// processedData[2] ( instrument = BTC/USD, positions = 2321)
Do you have any idea how can I do this ?
You can try Linq and query rawData:
var processedData = rawData
.Select(item => item.Split(';'))
.Select(items => new Data() {
instrument = items[0],
positions = items[1]
})
.ToList();
foreach(var rawString in rawData){
var split = rawString.Split(";");
processedData.Add(new Data(){
instruments = split[0],
positions = split[1]
});
}
You can try this code below
private static void TestFunc()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
var processedData = new List<Data1>();
foreach (var item in rawData)
{
var ins = item.Split(";")[0];
var pos = item.Split(";")[1];
processedData.Add(new Data1(ins, pos));
}
}
you can use linq
void Main()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
rawData.Select(s =>
new Data() {instrument= s.Split(";")[0],positions = (s.Split(";").Count() > 1) ? s.Split(";")[1] : null})
.ToList().Dump();
}
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}
passing a string like this to the code behind:
0,-1|1,-1|2,-1|3,-1|4,-1|5,-1|6,-1|7,-1|8,-1
I need to be able to asign the values before and after the "," symbol per each "|" symbol that exits in the string, into separated variables, "line" for first value (before the ",") and "group" for the next one (after the ",").
Right now I'm trying with this, but I'm having some issues with converting from string[] to string.
public static string GuardarGrupos(string parametro){
var data = parametro.Split(Convert.ToChar("|"));
var datos = "";
string[] linea;
var grupo = "";
//Iterate through each of the letters
foreach (var check in data)
{
datos = data[0];
linea = data[0].Split(Convert.ToChar(","));
}
return linea;
}
Any Idea how can I achieve this?
Make a class or struct to hold your values:
public class DataObject
{
public string X {get; set;}
public string Y {get; set;}
}
Return a List<T> of type DataObject
public static List<DataObject> GuardarGrupos(string parametro){
//List to return
List<DataObject> returnList = new List<DataObject>();
//Split the string on pipe to get each set of values
var data = parametro.Split('|'); //No need to do a convert.char(),
//String.Split has an overload that takes a character, use single quotes for character
//Iterate through each of the letters
foreach (var check in data)
{
//Split on comma to get the individual values
string[] values = check.Split(',');
DataObject do = new DataObject()
{
X = values[0];
Y = values[1];
};
returnList.Add(do);
}
return returnList;
}
Once you have the List<DataObject>, you can form line and group using linq and string.Join:
List<DataObject> myList = GuardarGrupos("0,-1|1,-1|2,-1|3,-1|4,-1|5,-1|6,-1|7,-1|8,-1");
string line = string.Join(",", myList.Select(x => x.X);
string group = string.Join(",", myList.Select(y => y.Y);
Instead of using local variables , create a Class that stores your retrieved values. then in the main you could handle/manipulate those values as required.
public class MyData
{
public string Datos { get; set; }
public string Linea { get; set; }
public string Grupo { get; set; }
}
public static List<MyData> myFunction(string parametro)
{
List<MyData> result = new List<MyData>();
var data = parametro.Split(Convert.ToChar("|"));
foreach (var check in data)
{
MyData temp = new MyData();
var line = check.Split(',');
temp.Datos = line[0];
temp.Linea = line[1];
temp.Grupo = check;
result.Add(temp);
}
return result;
}
static void Main(string[] args)
{
var t = myFunction("0,-1|1,-1|2,-1|3,-1|4,-1|5,-1|6,-1|7,-1|8,-1");
}
Here is a robust solution that's just a simple iteration over a string.
void Main()
{
var xs = "0,-1|1,-1|2,-1|3,-1|4,-1|5,-1|6,-1|7,-1|8,-1";
var stack = new Stack<Pair>();
stack.Push(new Pair());
foreach(var x in xs)
if(x == '|')
stack.Push(new UserQuery.Pair());
else
stack.Peek().Accept(x);
foreach (var x in stack.Reverse())
Console.WriteLine(x);
}
sealed class Pair
{
Action<char> _Accept;
readonly List<char> Line = new List<char>();
readonly List<char> Group = new List<char>();
public Pair()
{
_Accept = x => Line.Add(x);
}
public void Accept(char c)
{
if(c == ',')
_Accept = x => Group.Add(x);
else
_Accept(c);
}
public override string ToString()
{
return "Line:" + new string(Line.ToArray()) + " Group:" + new string(Group.ToArray());
}
}
I have the following:
public class Address{
public string Number { get; set; }
public string Street { get; set; }
public string Suburb { get; set; }
}
List<Address> MyAddressList = new List<Address>();
Address MyAddress = new Address();
myAddress.Number = "5"
myAddress.Street = "Smith St"
myAddress.Suburb = "Smithsville"
MyAddressList.Add(MyAddress);
Address MyAddress2 = new Address();
myAddress2.Number = "10"
myAddress2.Street = "John St"
myAddress2.Suburb = "Johnsville"
MyAddressList.Add(MyAddress2);
string [] StreetToFind = new string {"Smith St"};
string [] SuburbToFind = new string {"Smithsville"};
string [] secondSuburbToFind = new string {"Johnsville"};
I want to search through this list and look for a combination of values and return a bool if the combination is found.
To start, I can search for an individual value in the Street Property:
bool StreetIsFound = MyAddressList.Select(x => x.Street).Intersect(StreetToFind).Any();
and the same for Suburb:
bool SuburbIsFind = = MyAddressList.Select(x => x.Suburb).Intersect(SuburbToFind).Any();
but I want to be able to search for both in a combination (bool StreetandSuburbFound)
so that if I searched for StreetToFind and SuburbToFind, StreetandSuburbFound would be true but would be false if searching for StreetToFind and secondSuburbToFind.
You can do this all with one call to Any. Like this
var isFound = MyAddressList.Any(x => StreetToFind.Contains(x.Street) && SuburbToFind.Contains(x.Suburb));
Or in query syntax
var isFound =
(from x in MyAddressList
where StreetToFind.Contains(x.Street)
&& SuburbToFind.Contains(x.Suburb)
select x)
.Any();
Or the method chain version of p.s.w.g's code:
MyAddressList.Any(x => StreetToFind.Contains(x.Street)
&& SuburbToFind.Contains(x.Suburb))
(obviously tweak as neccessary with the Contains etc)
Can I restructure the following into a more compact linq query, ideally without the introduction of a helper function?
var revPerUnitChanges =
from row in this.DataTable.GetChanges(DataRowState.Modified).AsEnumerable()
let field = "Rev/Unit"
select new {
Field = field,
From = row.Field<decimal>(field, DataRowVersion.Original),
To = row.Field<decimal>(field, DataRowVersion.Current),
ItemIds = row.Field<string>("ItemIds"),};
var costPerUnitChanges =
from row in this.DataTable.GetChanges(DataRowState.Modified).AsEnumerable()
let field = "Cost/Unit"
select new {
Field = field,
From = row.Field<decimal>(field, DataRowVersion.Original),
To = row.Field<decimal>(field, DataRowVersion.Current),
ItemIds = row.Field<string>("ItemIds"), };
var numUnitsChanges =
from row in this.DataTable.GetChanges(DataRowState.Modified).AsEnumerable()
let field = "Units"
select new {
Field = field,
From = row.Field<decimal>(field, DataRowVersion.Original),
To = row.Field<decimal>(field, DataRowVersion.Current),
ItemIds = row.Field<string>("ItemIds"), };
var changes =
revPerUnitChanges
.Concat(costPerUnitChanges
.Concat(numUnitsChanges))
.Where(c => c.From != c.To);
Start out by creating a helper class to hold onto the data. (Your code doesn't have any problems using anonymous types, but if you want to refactor sections into methods it'll be much easier with a named class.)
public class MyClass //TODO give better name
{
public MyClass(DataRow row, string field) //You could have a public static generate method if it doesn't make sense for this to be a constructor.
{
Field = field;
From = row.Field<decimal>(field, DataRowVersion.Original);
To = row.Field<decimal>(field, DataRowVersion.Current);
ItemIds = row.Field<string>("ItemIds");
}
public string Field { get; set; }
public decimal From { get; set; }
public decimal To { get; set; }
public string ItemIds { get; set; }
}
Now that we have that out of the way the query is fairly straightforward.
var changes = dataTable.GetChanges(DataRowState.Modified)
.AsEnumerable()
.Select(row => new[]{ //create 3 new items for each row
new MyClass(row, "Rev/Unit"),
new MyClass(row, "Cost/Unit"),
new MyClass(row, "Units"),
})
.SelectMany(item => item) //flatten the inner array
.Where(item => item.From != item.To);