【问题标题】:Reverse format string and determinate correct result反转格式字符串并确定正确的结果
【发布时间】:2020-03-01 13:26:05
【问题描述】:

我必须反转格式字符串以提取“电子邮件”并确定正确的布尔结果。

string input = "The Email field is required.";

string required = "The {0} field is required.";
string date = "The {0} field is not a valid date.";

bool isRequired = false;
bool isDate = false;

string extractedField;

我的期望是将值“Email”设置为“extractedField”,将“isRequired”设置为 true

更新: 对不起,如果我在解释自己时过于笼统。为了更好地阐明我的意图,我创建了一个小提琴https://dotnetfiddle.net/cjPAo1

【问题讨论】:

  • 提供更好的输入字符串样本。您是否要获取字符串的第二个单词?使用字符串在空间上拆分并获取数组中的第二项。
  • 我用一个例子更新了帖子,以更好地解释我的意图。

标签: c# formatting reverse format-string


【解决方案1】:

我相信我理解您的查询。您想检查当前消息匹配的“表达式”,并根据它,将适当的标志设置为 true。同时检索有问题的“字段”。

实现它的一种方法是

更新

根据您的评论,已更新代码以支持多个字段。

string input = "Age should be between 1 and 99.";
string required = "The {0} field is required.";
string date = "The {0} field is not a valid date.";
string range = "{0} should be between {1} and {2}.";

bool isRequired = false;
bool isDate = false;
bool isRange = false;
string extractedField;


var possibilities = new []
                    {
                        new KeyValuePair<string,Action>(ToRegex(required), ()=>((Action)(() => { isRequired = true;}))()),
                        new KeyValuePair<string,Action>(ToRegex(date), ()=>((Action)(() => { isDate = true;}))()),
                        new KeyValuePair<string,Action>(ToRegex(range), ()=>((Action)(() => { isRange = true;}))())
                    };
var result = possibilities
             .Where(x=>Regex.Match(input,x.Key).Success)
             .Select(x=> new KeyValuePair<IEnumerable<string>,Action>( 
                                            Regex.Match(input,x.Key).Groups.Cast<Group>().Where(c=>c.Name.StartsWith("Field")).Select(c=>c.Value),
                                            x.Value)).First();


var fields = result.Key;
result.Value();
Console.WriteLine($"{nameof(extractedField)}={string.Join(",",fields)},{Environment.NewLine}{nameof(isRequired)}={isRequired},{Environment.NewLine}{nameof(isDate)}={isDate}");

ToRegex 定义为

public string ToRegex(string value)
{
    var result = new List<string>();
    foreach(var item in value.Split(' '))
    {
        if(Regex.Match(item,@"{(?<Value>\d*)}").Success)
        {
            var match = Regex.Match(item,@"{(?<Value>\d*)}");

            result.Add(Regex.Replace(item,@"{(?<Value>\d*)}",$"(?<Field{match.Groups["Value"].Value}>\\S*)"));
            continue;
        }
        result.Add(item);
    };
    return string.Join(" ",result);
}

Demo Code

上面的代码使用正则表达式来寻找合适的匹配。

样本输出

extractedField=Age,1,99,
isRequired=False,
isDate=False

更新

根据您的评论,要支持多个单词,您可以使用以下内容。

public string ToRegex(string value)
{
    var result = new List<string>();
    foreach(var item in value.Split(' '))
    {
        if(Regex.Match(item,@"{(?<Value>\d*)}").Success)
        {
            var match = Regex.Match(item,@"{(?<Value>\d*)}");

            result.Add(Regex.Replace(item,@"{(?<Value>\d*)}",$"(?<Field{match.Groups["Value"].Value}>[\\S ]*)"));
            continue;
        }
        result.Add(item);
    };
    return string.Join(" ",result);
}

【讨论】:

  • 是的,这就是我要找的!谢谢你。您认为可以提取多个字段,例如此处dotnetfiddle.net/frFXYn 的“范围”示例?我不在乎返回所有结果(首先就足够了),而只是填充提取字段上的字段
  • @Sauron 请检查更新后的代码。我还更新了代码以使用 Regex 而不是 Split-Word-Compare 方法,它还支持多个字段。请检查点小提琴链接
  • 我认为这个答案是正确的,因为它是第一个有效的解决方案,描述得很好,适合各种用途。
  • 嗨@Anu Viswan,我注意到如果我用“需要新密码字段”更改输入。它不再起作用了。看起来 ToRegex 方法只接受单个单词dotnetfiddle.net/SpLwum。非常感谢。
  • @Sauron 我已经更新了答案以支持该场景,请验证
【解决方案2】:

使用Regex.Match,函数ExtractFieldAndDeterminateType可以写成:

public static string ExtractFieldAndDeterminateType(string input, out Type type)
{
    var extractedField = "";
    string required = "The (.*) field is (.*).";
    //string date = "The (.*) field is not a (.*)."; => Not needed
    string range = "(.*)(?= should be between)";
    type = Type.Unknown;

    var match = Regex.Match(input, required);
    if (match.Success)
    {
        extractedField = match.Groups[1].Value;
        switch (match.Groups[2].Value)
        {
            case "required":
                type = Type.Error;
                break;
            case "not a valid date":
                type = Type.Date;
                break;
        }
    }
    else if ((match = Regex.Match(input, range)).Success)
    {
        extractedField = match.Groups[1].Value;
        type = Type.Range;
    }
    else
    {
        //Nothing 
    }
    return extractedField;
}

OP 的测试数据输出:

Field is: Email and Type is: Error
Field is: Username and Type is: Error
Field is: InsertDate and Type is: Date
Field is: Age and Type is: Range

已编辑:为小提琴Link to fiddle添加了示例代码

【讨论】:

    【解决方案3】:

    尝试以下:

        class Program
        {
            static void Main(string[] args)
            {
                string[] inputs = {
                                      "The Email field is required.",
                                      "The Username field is required.",
                                      "The InsertDate field is not a valid date.",
                                      "Age should be between 1 and 99."
                                  };
                Type type;
                foreach (string input in inputs)
                {
                    string word = ExtractFieldAndDeterminateType(input, out type);
                    Console.WriteLine(word);
                }
                Console.ReadLine();
            }
            public static string ExtractFieldAndDeterminateType(string input, out Type type)
            {
                string[] words = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    
                int index = 0;
                if (words[0] == "The") index = 1;
    
                string word = words[index];
    
                switch (word)
                {
                    case "Email" :
                        type = typeof(string);
                        break;
    
                    case "Username":
                        type = typeof(string);
                        break;
    
                    case "InsertDate":
                        type = typeof(DateTime);
                        break;
    
                    case "Age":
                        type = typeof(int);
                        break;
    
                    default:
                        type = (Type)Type.Missing;
                        break;
                }
    
                return word;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2017-09-25
      • 2012-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-05
      • 2017-04-28
      • 1970-01-01
      相关资源
      最近更新 更多