1

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.

2 Answers 2

1

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)

Sign up to request clarification or add additional context in comments.

2 Comments

I'm wondering if I need the starting position in the dictionary and whether I need a Tuple at all? Anyway I'll mark your response as Answer. Cheers
@ErshadNozari Sure, Tuple was just for convenience. You could just as easily decompose the rule's key to grab the id and expected along with the actual and return it as an anonymous type or 3 item tuple (I added an example select statement to this effect.)
0

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 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.