【问题标题】:Reading numbers from string in C#从 C# 中的字符串中读取数字
【发布时间】:2009-09-21 10:52:32
【问题描述】:

我想要什么?

我想在我的页面上显示天气信息。 我想以浏览器特定的文化显示结果。

我在做什么?

我为此目的使用 MSN RSS。 MSN 以 XML 格式返回报告。我解析 XML 并显示结果。

我面临什么问题?

在显示报告时,我必须解析一个 XML 节点 <data>,这将是不同文化中不同的值。

例如,

美国:"Lo: 46°F. Hi: 67°F. Chance of precipitation: 20%"

de-DE:"Niedrig: 46°F. Höchst: 67°F. Niederschlag %: 20%"

我只想读取降水值的低、高和几率。即,我想读取 46、67 和 20%。

有人可以给我一个解决方案吗?

可能是 RegX 或其他方法我也可以 :-)

提前致谢!

【问题讨论】:

  • 即使在德国语言环境中,您也能以°F 为单位获得温度?让我想知道拥有所有这些特定文化的意义何在,实际上......
  • 对不起,我使用的 URL 有一个查询字符串,要求报告在 F 中:)。我使用的网址是这样的:weather.msn.com/…
  • 好吧,既然你在查询字符串中保留了文化,你为什么还要这样做呢?如果您只对数字感兴趣,那么为什么还要打扰您甚至不需要的其他语言环境?
  • +1 表示一个清晰且写得很好的问题 :-)
  • @Johannes Rössel:实际上,我不应该在查询字符串中保留文化。这是我在形成问题时犯的错误。 :)

标签: c# .net regex


【解决方案1】:

您应该考虑始终使用相同的文化来获取 RSS。这样,您将更轻松地解析内容。如果您只使用数字,则不应阻止您向最终用户发送特定文化的内容。

所以如果你选择 en-US 版本,你可以这样做:

Regex re = new Regex(@"Lo: (\d+)°F. Hi: (\d+)°F. Chance of precipitation: (\d+)%");
var match = re.Match(forecast);
if (match.Success)
{
    var groups = match.Groups;
    lo = int.Parse(groups[1].Captures[0].Value);
    hi = int.Parse(groups[2].Captures[0].Value);
    prec = int.Parse(groups[3].Captures[0].Value);
}

【讨论】:

  • 我结合了你和 Johannes Rössel 的答案来解决我的问题。谢谢!
【解决方案2】:

如果你只想要数字,你可以使用正则表达式,例如:

(\d+).*?(\d+).*?(\d+%)

PowerShell 中的快速测试表明它至少对您的输入数据有效:

PS Home:\> function test ($re) {
>>   $a -match $re; $Matches
>>   $b -match $re; $Matches
>> }
>>
PS Home:\> $a = "Lo: 46°F. Hi: 67°F. Chance of precipitation: 20%"
PS Home:\> $b = "Niedrig: 46°F. Höchst: 67°F. Niederschlag %: 20%"
PS Home:\> test "(\d+).*?(\d+).*?(\d+%)"
True

Name                           Value
----                           -----
3                              20%
2                              67
1                              46
0                              46°F. Hi: 67°F. Chance of precipitation: 20%
True
3                              20%
2                              67
1                              46
0                              46°F. Höchst: 67°F. Niederschlag %: 20%

但是,如果任何语言环境可能在描述字符串中使用数字,它将不再起作用。

您可以添加其他约束,例如在每个匹配项前都需要一个冒号:

: (\d+).*?: (\d+).*?: (\d+%)

这应该处理字符串中其他地方的虚假数字。但总体而言,最好的方法实际上是从为您提供机器阅读数据的来源获取数据,而不是供人类消费

【讨论】:

  • 正则表达式有效。我结合了你和 Tor Haugen 的答案来解决我的问题。谢谢!
【解决方案3】:

下面应该提取两个数字和降水机会,以及使用的单位(对于文化相关单位)。

(?<lo>\d+°.).*?(?<hi>\d+°.).*?(?<precipitation>\d+)

如果你不想提取单位,那么你可以使用

(?<lo>\d+)°.*?(?<hi>\d+)°.*?(?<precipitation>\d+)

【讨论】:

    【解决方案4】:

    使用正则表达式(但我不知道正则表达式;))

    您还可以对句子执行 forloop,并检查每个字符是否为整数。每次遇到一次,把它放在一个字符串中。当找到除整数以外的其他内容时,将字符串解析为 int 并瞧。这样做 3 次

    【讨论】:

    • 当然!我可以做这个。但是,这是最好的解决方案吗?
    • 我会做一个像约翰内斯这样的正则表达式。绝对更干净,但更难阅读。
    • 顺便说一句,没有最好的解决方案。每个解决方案都有其优点和缺点。 regex pro:干净、更小并且可能更快。正则表达式:难以阅读,难以掌握正则表达式
    • 好的。让我检查一下。谢谢:)
    【解决方案5】:

    很奇怪,您没有在不同节点中获取具有值的 XML,这对我来说更有意义(您可以选择用于不同语言环境的值)。

    但是,如果你想从给定的字符串中提取数据,如果你不是 RegEx 的粉丝,试试这个或类似的东西:

    string dataUS = "Lo: 46°F. Hi: 67°F. Chance of precipitation: 20%";
    string dataDE = "Niedrig: 46°F. Höchst: 67°F. Niederschlag %: 20%";
    string[] stringValues = dataU.Split(new string[] {": "}, 4, StringSplitOptions.None);
    List<int> values = new List<int>();
    for (int i = 1; i < 4; i++)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char c in stringValues[i].Trim())
        {
            if (Char.IsDigit(c))
            {
                sb.Append(c);
            }
            else
            {
                values.Add(Convert.ToInt32(sb.ToString()));
                break;
            }
        }
    }
    

    (我在“:”而不是数字上拆分)

    【讨论】:

      【解决方案6】:

      我建议使用正则表达式根据 UI 文化语言一一获取您想要的值: 我的意思是你可以有一个正则表达式来获得 Lo temp。 "(Lo|Niedrig):(\d+)" ,一个获取 Hi temp 的正则表达式 "(Hi|Höchst):(\d+)" 和一个正则表达式来获得感知的机会等等。 在上述所有示例中,您都可以从匹配的第二个元素中获取数字。

      【讨论】:

      • 您还可以对文字部分使用非分组括号:(?:Lo|Niedrig) 以避免出现您不做任何事情的组。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-05
      • 2014-01-21
      • 2021-09-13
      • 2012-11-28
      • 1970-01-01
      相关资源
      最近更新 更多