【问题标题】:C# LINQ and Pattern Matching challengeC# LINQ 和模式匹配挑战
【发布时间】:2018-05-15 23:45:25
【问题描述】:

我需要一个解决方案来检查固定长度字符串的内容是否符合一组规则。如果没有,我需要检索失败的 Rules 列表、每个规则的 Expected 值以及包含在细绳。

这是我目前的解决方案:

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

我确信有更好的方法来解决这个问题。此外,就目前而言,我对这个解决方案并不完全满意,因为它没有给我实际的字段。

谢谢。

【问题讨论】:

    标签: c# regex linq pattern-matching


    【解决方案1】:

    有什么理由不能将规则与检查的部分一起包装在一个元组中?

    如果没有,我会这样做:

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

    然后,根据您上面的示例,输出:

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

    您也可以在选择中进一步解压规则条目,类似于select (field.Key.Item1, field.Key.Item2, inspected);,您最终会得到一个 (RuleId, expected, actual) 元组

    【讨论】:

    • 我想知道是否需要字典中的起始位置以及是否需要元组?无论如何,我会将您的回复标记为答案。干杯
    • @ErshadNozari 当然,Tuple 只是为了方便。您可以轻松地分解规则的键以获取 id 和预期以及实际并将其作为匿名类型或 3 项元组返回(我为此添加了一个示例 select 语句。)
    【解决方案2】:

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

    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&lt;Rule&gt; 来保存规则:

    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 }
    

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 2016-02-06
      • 2021-09-09
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多