【问题标题】:Is there a way that I can simplify setting a value based on what is contained in a string?有没有一种方法可以简化根据字符串中包含的内容设置值?
【发布时间】:2019-10-15 03:49:46
【问题描述】:

目前我的代码是这样的,但我想知道是否有一种方法可以简化它。我正在寻找的是其中一个字符串 "JLPT N1","JLPT N2","JLPT N3","JLPT N4","JLPT N5" 然后当我看到其中一个字符串时,我将设置 a phraseSources[seq].JishoJlpt

请注意,一次只能出现以上其中一项。

            if (nodes2[0].InnerText.Contains("JLPT N5"))
            {
                phraseSources[seq].JishoJlpt = "5";
            }
            if (nodes2[0].InnerText.Contains("JLPT N4"))
            {
                phraseSources[seq].JishoJlpt = "4";
            }
            if (nodes2[0].InnerText.Contains("JLPT N3"))
            {
                phraseSources[seq].JishoJlpt = "3";
            }
            if (nodes2[0].InnerText.Contains("JLPT N2"))
            {
                phraseSources[seq].JishoJlpt = "2";
            }
            if (nodes2[0].InnerText.Contains("JLPT N1"))
            {
                phraseSources[seq].JishoJlpt = "1";
            }

如果有人能建议我如何简化这一点,我将不胜感激。

【问题讨论】:

  • 是 N1,2,3.. 会超过 9 吗?
  • 你控制JSON数据的格式吗?

标签: c#


【解决方案1】:

您应该查看Regular Expressions

此方法将从您的文本中获取int,然后您可以使用它。

    using System.Linq;
    using System.Text.RegularExpressions;

    public int ContainedNum(string s)
    {
        var match = Regex
           .Match(s, (@"JLPT N(\d{1})"))
           .Groups
           .Cast<Group>()
           .Skip(1) // the first match is the entire string not the group
           .Single()
           .Value;
        var num = int.Parse(match);
        return num;
    }

这假设 每个参数 总是遵循这种模式并且不大于9。如果不是这种情况,您需要更加保守地使用Single() 并弄清楚如果不是这种情况您想要返回什么。

你可以这样使用它:

var text = nodes2[0].InnerText;
var num = ContainedNum(text);
phraseSources[seq].JishoJlpt = num.ToString();

【讨论】:

  • 如果没有其他更改,^JLPT N(\d{1:3}) 不能用于 1-3 位数字吗?
  • 由于 OP 使用 Contains 我不认为你想使用 ^ 锚。此外,将数字解析为int 以将其转回并将其格式化回string 似乎没有多大意义。
  • @juharr 好电话。我删除了^。我意识到强制转换为 int 是不必要的,但在处理数字时,我喜欢在 signature 中明确说明。
【解决方案2】:

我喜欢 Try pattern 进行这种解析:

private static bool TryParseJLPT(string text, out int value)
{
    var match = Regex.Match(text, @"JLPT N(?<Number>\d+)", RegexOptions.None);
    if (!match.Success) { value = default; return false; }
    return Int32.TryParse(match.Groups["Number"].Value, out value);
}

使用示例:

if (TryParseJLPT(nodes2[0].InnerText, out int value))
{
    phraseSources[seq].JishoJlpt = value;
}

根据情况,抛出而不是返回布尔值可能更合适。如果解析失败是可以处理的预期情况,那么 Try 模式是可以的。如果解析失败是异常的并且您不知道如何继续,那么抛出更好。

【讨论】:

    【解决方案3】:

    为什么不使用扩展?

    我一直在使用这个扩展程序:

    internal static class Extensions
    {
        public static bool In(this string value, params string[] args)
        {
            return args.Contains(value);
        }
    
    }
    

    在您的代码上应用In 扩展将是这样的:

    if (nodes2[0].InnerText.In("JLPT N1","JLPT N2","JLPT N3","JLPT N4","JLPT N5"))
    {
        phraseSources[seq].JishoJlpt = nodes2[0].InnerText.Last(); // get the last character
    }
    

    【讨论】:

    • OP 的代码正在检查这些值是否是InnerText 的子字符串,因此这与它们的代码不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 1970-01-01
    • 2012-02-25
    相关资源
    最近更新 更多