Reputation: 667
I need a solution that checks whether the content of a string of fixed lenght adheres to a set of rules. If not, I need to retrieve a list of the Rules that failed, the Expected value for each rule, and the Actually value contained within the string.
This is my current solution:
string actual = "628IDENTREGISTER153004085616P30062010EAPFEMPA013.1";
// Dictionary<Tuple<rule, expected>, startingPostion>
var expected = new Dictionary<Tuple<string, string>, int>
{
{new Tuple<string, string>("900052", "628"), 0},
{new Tuple<string, string>("9000250", "IDENTREGISTER1"), 3},
{new Tuple<string, string>("900092", "53004085616"), 17},
{new Tuple<string, string>("900004", "P"), 28},
{new Tuple<string, string>("900089", "30062010"), 29},
{new Tuple<string, string>("900028", "E"), 37},
{new Tuple<string, string>("900029", "A"), 38},
{new Tuple<string, string>("900002", "P"), 39},
{new Tuple<string, string>("900030", "FEMPA013.0"), 40}
};
// Create an IEnumerable of all broken rules
var result = expected.Where(field =>
!field.Key.Item2.Equals(
actual.Substring(field.Value, field.Key.Item2.Length)))
// Prints:
// [(900030, FEMPA013.0), 40]
foreach (var res in result)
Console.WriteLine(res);
I'm sure there’s a better way of solving this problem. Also, as it stands, I’m not entirely satisfied with this solution as it does not give me the actual field.
Thanks.
Upvotes: 1
Views: 953
Reputation: 9704
Any reason you couldn't just wrap the rule along with the inspected portion in a Tuple?
If not, I would do something like this:
var result = from field in expected
let inspected = actual.Substring(field.Value, field.Key.Item2.Length)
where !field.Key.Item2.Equals(inspected)
select (field, inspected);
Which would then, given your example above, output:
([(900030, FEMPA013.0), 40], FEMPA013.1)
You could unpack the rule entry a little further in the select as well, something along the lines of select (field.Key.Item1, field.Key.Item2, inspected);
, and you'll end up with a tuple of (RuleId, expected, actual)
Upvotes: 1
Reputation: 26917
You should create a class to represent a rule, and have some helper methods in the class:
public class Rule {
public string RuleName;
public string Expected;
public int StartPos;
public bool IsMatch(string actual) => Field(actual) == Expected;
public string Field(string actual) => actual.Substring(StartPos, Math.Min(Expected.Length, actual.Length-StartPos));
public override string ToString() => $"{{ {RuleName}: @{StartPos}=\"{Expected}\" }}";
}
Now you can just need a List<Rule>
to hold the rules:
var expected = new List<Rule> {
new Rule { RuleName = "900052", Expected = "628", StartPos = 0 },
new Rule { RuleName = "9000250", Expected = "IDENTREGISTER1", StartPos = 3 },
new Rule { RuleName = "900092", Expected = "53004085616", StartPos = 17 },
new Rule { RuleName = "900004", Expected = "P", StartPos = 28 },
new Rule { RuleName = "900089", Expected = "30062010", StartPos = 29 },
new Rule { RuleName = "900028", Expected = "E", StartPos = 37 },
new Rule { RuleName = "900029", Expected = "A", StartPos = 38 },
new Rule { RuleName = "900002", Expected = "P", StartPos = 39 },
new Rule { RuleName = "900030", Expected = "FEMPA013.0", StartPos = 40 }
};
And you can find the bad rules and extract the bad fields:
string actual = "628IDENTREGISTER153004085616P30062010EAPFEMPA013.1";
var result = expected.Where(rule => !rule.IsMatch(actual)).Select(rule => new { rule, Actual = rule.Field(actual) });
foreach (var res in result)
Console.WriteLine(res);
// Output is
// { rule = { 900030: @40="FEMPA013.0" }, Actual = FEMPA013.1 }
Upvotes: 0