从琴弦中提取温度

时间:2018-07-19 16:23:14

标签: c# string algorithm substring

我目前正在尝试从字符串中提取值。所述字符串包含从CPU获取的REAL温度值:

I.E。 (基于四核CPU)

    40.5 °C 42.4 °C 39.9 °C 40.0 °C 

(包含空格|取决于核心数,可能会有更少/更多的临时文件)

我目前正在尝试从单数字符串中获取每个值,然后使用这些值查找平均值。虽然我已经找到解决方法,但我的解决方案效率低下,包含多个循环等。

此函数用于查找实时更新的XAML上显示的CPU温度的不断更新的值,因此算法需要尽可能高效。

如果您想寻求一种高效的算法,我将不胜感激!

5 个答案:

答案 0 :(得分:4)

这是正则表达式(缩写为“ regex”)的理想选择。

var input = "40.5 °C 42.4 °C 39.9 °C 40.0 °C ";
var regex = new Regex(@"\d{1,2}\.\d");
var matches = regex.Matches(input);

foreach (Match m in matches)
{
    Debug.WriteLine(m.Value);
}

好的,这是做什么的?

var regex = new Regex(@"\d{1,2}\.\d");

这将设置具有特定格式的新正则表达式。在这种情况下,我们要匹配:

  • \d{1,2}{1,2}表示将前面的令牌匹配1-2次。我假设您的温度范围是0.0到99.0。如果超出此范围,则需要修改此行。您可以将范围更改为\d{1,3}以允许第三个数字,或者将\d+允许一个或多个连续数字。
  • \.:一个句点-必须省略句点,因为句点在正则表达式中具有特殊含义
  • \d:1位数字

第三行从输入字符串中获取所有匹配的子表达式。其余代码会将结果吐入“调试”窗口以进行演示。

答案 1 :(得分:4)

由于使用非常方便的System.String.Split()函数没有答案,因此-这里是一个:

double[] Parse(string s)
{
    var valueStrings = s.Split(new string[] { " ", "°C" }, 
        System.StringSplitOptions.RemoveEmptyEntries);
    return valueStrings.Select(xs => System.Double.Parse(xs)).ToArray();
}

理论上,手工编织的实现可能会更快,因为从技术上讲,此解决方案在字符串上进行迭代,然后在拆分结果上进行迭代。仅需一次迭代即可完成这两个步骤。但是由于您拥有的内核数量将受到限制(我有6个内核,有些具有32或64个内核-但只有少数具有更多内核),因此上述代码的性能应该足够。

答案 2 :(得分:1)

正如Amy在评论中所说,使用Regex可以轻松解决此问题。
如果您想了解有关正则表达式的更多信息,建议您查看以下内容:https://regexr.com/
如果您想测试自己的正则表达式,建议您使用:https://regex101.com

无论如何,要解决您的问题,我们将使用正则表达式以°C为常量来捕获数字(40.5、42.4等)为一组: ([0-9]+(\.[0-9][0-9]?)?) °Ctry it)。

[0-9]+(\.[0-9][0-9]?)?捕获几乎所有可能的十进制数字,因此它应该涵盖所有可能的温度。

这将为您提供一组号码,然后您可以根据需要使用该号码。在C#环境中:

string str = "40.5 °C 42.4 °C 39.9 °C 40.0 °C ";
foreach (Match match in Regex.Matches(str, @"([0-9]+(\.[0-9][0-9]?)?) °C"))
{
    Console.WriteLine(match.Groups[1].Value);
}

答案 3 :(得分:1)

这是正则表达式解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApplication55
{
    class Program
    {
        static void Main(string[] args)
        {
            string input = "40.5 °C 42.4 °C 39.9 °C 40.0 °C";
            string pattern = "(?'temp'[^ ]+) °C";

            decimal[] temperatures = Regex.Matches(input, pattern).Cast<Match>().Select(x => decimal.Parse(x.Groups["temp"].Value)).ToArray();
        }
    }
}

答案 4 :(得分:-4)

OP明确了他的要求,以允许单位温度。给你。

string temps = "1.1 °C 40.5 °C 42.4 °C 39.9 °C 40.0 °C 4.0 °C 11.1 °C";
decimal sum = 0m;
int count = 0;
for (int i = 0; i < temps.Length; i += temps[i + 4] == ' ' ? 8 : 7)
{
    string t = temps.Substring(i, 4).TrimEnd();
    Console.WriteLine(t);
    sum += Decimal.Parse(t);
    count++;
}
decimal avg = sum / count;
Console.WriteLine("Avg = " + avg.ToString());

这应该比基于正则表达式的解决方案高效得多。

通过从字符串中获取4个字符,将其转换为小数,然后将其添加到总和中来工作。然后,根据第四个字符是否为空格,它会向前跳7个或8个字符以查找下一个温度。

这样的算法非常快,因为它完成该工作所需的工作量最少。