C#LINQ和模式匹配挑战

时间:2018-05-15 23:45:26

标签: c# regex linq pattern-matching

我需要一个解决方案来检查固定长度字符串的内容是否符合一组规则。如果没有,我需要检索失败的规则列表,每个规则的预期值以及其中包含的实际值串。

这是我目前的解决方案:

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);

我确信有更好的方法可以解决这个问题。而且,就目前而言,我对这个解决方案并不完全满意,因为它没有给我实际的领域。

感谢。

2 个答案:

答案 0 :(得分:1)

你有什么理由不能将规则与元组中的被检部分一起包裹吗?

如果没有,我会做这样的事情:

{
  "data": {
    "id": "websites",
    "type": "table",
    "attributes": {
      "data": [
        {
          "name": "facebook.com",
          "id": "1",
          ...
        },
        {
          "name": "google.com",
          "id": "2",
          ...
        },
        {
          "name": "twitter.com",
          "id": "3",
          ...
        {
      ]
    }
  }
}

根据上面的例子,那将输出:

  

([(900030,FEMPA013.0),40],FEMPA013.1)

您可以在选择中进一步解压缩规则条目,类似于{ entities: { "1": { "name": "facebook.com", "id": "1", ... }, "2": { "name": "google.com", "id": "2", ... }, "3": { "name": "twitter.com", "id": "3", ... } }, results: ["1", "2", "3"] } 的行,您最终会得到(RuleId,expected,actual)元组

答案 1 :(得分:0)

您应该创建一个表示规则的类,并在类中使用一些辅助方法:

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}\" }}";
}

现在您只需要List<Rule>来保存规则:

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 }
 };

你可以找到不好的规则并提取坏字段:

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 }