211 lines
9.0 KiB
C#
211 lines
9.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text.RegularExpressions;
|
||
|
||
namespace VoiceToFunction
|
||
{
|
||
|
||
class Program
|
||
{
|
||
// 初始化函数库(明确参数类型要求)
|
||
private static List<FunctionInfo> functionLibrary = new List<FunctionInfo>
|
||
{
|
||
// 1. 乘积函数(参数:两个double数组)
|
||
new FunctionInfo
|
||
{
|
||
Name = "PRODUCT",
|
||
Description = "计算多列对应行的乘积",
|
||
Synonyms = new List<string> { "计算乘积", "相乘", "乘积" },
|
||
MinParams = 2,
|
||
ParamTypes = new List<Type> { typeof(double[]), typeof(double[]) },
|
||
Execute = (args) =>
|
||
{
|
||
double[] col1 = (double[])args[0];
|
||
double[] col2 = (double[])args[1];
|
||
return col1.Zip(col2, (a, b) => a * b).ToArray();
|
||
}
|
||
},
|
||
|
||
// 2. 筛选函数(参数:用户列表 + 筛选条件)
|
||
new FunctionInfo
|
||
{
|
||
Name = "FILTER",
|
||
Description = "筛选满足条件的数据",
|
||
Synonyms = new List<string> { "筛选", "过滤", "选出" },
|
||
MinParams = 2,
|
||
ParamTypes = new List<Type> { typeof(List<User>), typeof(Func<User, bool>) },
|
||
Execute = (args) =>
|
||
{
|
||
List<User> users = (List<User>)args[0];
|
||
Func<User, bool> condition = (Func<User, bool>)args[1];
|
||
return users.Where(condition).ToList();
|
||
}
|
||
},
|
||
|
||
// 3. 统计函数(参数:销售额数组 + 统计条件)
|
||
new FunctionInfo
|
||
{
|
||
Name = "COUNTIF",
|
||
Description = "统计满足条件的记录数",
|
||
Synonyms = new List<string> { "统计数量", "计数", "数一下" },
|
||
MinParams = 2,
|
||
ParamTypes = new List<Type> { typeof(double[]), typeof(Func<double, bool>) },
|
||
Execute = (args) =>
|
||
{
|
||
double[] sales = (double[])args[0];
|
||
Func<double, bool> condition = (Func<double, bool>)args[1];
|
||
return sales.Count(condition);
|
||
}
|
||
}
|
||
};
|
||
|
||
static void Main(string[] args)
|
||
{
|
||
// 测试带复杂参数的语音指令
|
||
TestVoiceCommand("计算C列和D列的乘积,C列是[1,3,5],D列是[2,4,6]");
|
||
TestVoiceCommand("计算A列和B列的乘积,A列是[1,3,5],B列是[2,4,6]");
|
||
TestVoiceCommand("筛选出年龄大于28且姓名包含'李'的用户");
|
||
TestVoiceCommand("统计销售额在5000到20000之间的订单数,数据是[3000, 8000, 15000, 25000]");
|
||
|
||
Console.ReadKey();
|
||
}
|
||
|
||
static void TestVoiceCommand(string voiceText)
|
||
{
|
||
Console.WriteLine($"=== 语音指令:{voiceText} ===");
|
||
ParsedResult result = ParseVoiceCommand(voiceText);
|
||
|
||
if (!string.IsNullOrEmpty(result.Error))
|
||
{
|
||
Console.WriteLine($"错误:{result.Error}");
|
||
return;
|
||
}
|
||
|
||
// 校验参数类型是否匹配函数要求
|
||
var function = functionLibrary.First(f => f.Name == result.FunctionName);
|
||
bool paramTypeMatch = function.ParamTypes.Zip(result.ParamTypes,
|
||
(required, actual) => required.Name == actual).All(match => match);
|
||
if (!paramTypeMatch)
|
||
{
|
||
Console.WriteLine("错误:参数类型与函数要求不匹配");
|
||
return;
|
||
}
|
||
|
||
// 执行函数并输出结果
|
||
var executionResult = function.Execute(result.Parameters);
|
||
Console.WriteLine($"匹配函数:{result.FunctionName}");
|
||
Console.WriteLine($"执行结果:{GetResultString(executionResult)}");
|
||
Console.WriteLine();
|
||
}
|
||
|
||
// 核心:解析语音文本,提取函数+参数(强化入参处理)
|
||
static ParsedResult ParseVoiceCommand(string text)
|
||
{
|
||
var result = new ParsedResult();
|
||
|
||
// 1. 匹配函数(同之前逻辑)
|
||
FunctionInfo matchedFunction = functionLibrary.FirstOrDefault(
|
||
func => func.Synonyms.Any(syn => text.Contains(syn)));
|
||
if (matchedFunction == null)
|
||
{
|
||
result.Error = "未找到匹配的函数";
|
||
return result;
|
||
}
|
||
result.FunctionName = matchedFunction.Name;
|
||
|
||
// 2. 提取并解析参数(根据函数类型动态处理)
|
||
try
|
||
{
|
||
switch (matchedFunction.Name)
|
||
{
|
||
case "PRODUCT":
|
||
// 提取列数据(支持显式输入如"[1,3,5]")
|
||
var colDataMatches = Regex.Matches(text, @"\[([\d, ]+)\]")
|
||
.Cast<Match>()
|
||
.Select(m => m.Groups[1].Value.Split(',').Select(double.Parse).ToArray())
|
||
.ToList();
|
||
if (colDataMatches.Count < 2)
|
||
{
|
||
result.Error = "PRODUCT需要至少两列数据,格式如'[1,2,3]'";
|
||
return result;
|
||
}
|
||
result.Parameters = new object[] { colDataMatches[0], colDataMatches[1] };
|
||
result.ParamTypes = new[] { "Double[]", "Double[]" };
|
||
break;
|
||
|
||
case "FILTER":
|
||
// 提取年龄条件(如"大于28")和姓名条件(如"包含'李'")
|
||
int ageThreshold = 0;
|
||
string nameKeyword = null;
|
||
|
||
var ageMatch = Regex.Match(text, @"年龄(大于|小于|等于)(\d+)");
|
||
if (ageMatch.Success)
|
||
{
|
||
string op = ageMatch.Groups[1].Value;
|
||
ageThreshold = int.Parse(ageMatch.Groups[2].Value);
|
||
}
|
||
|
||
var nameMatch = Regex.Match(text, @"姓名包含'([^']+)'");
|
||
if (nameMatch.Success)
|
||
{
|
||
nameKeyword = nameMatch.Groups[1].Value;
|
||
}
|
||
|
||
// 组合多条件筛选器
|
||
Func<User, bool> condition = u =>
|
||
(ageMatch.Success ? (ageMatch.Groups[1].Value == "大于" ? u.Age > ageThreshold : u.Age < ageThreshold) : true) &&
|
||
(nameMatch.Success ? u.Name.Contains(nameKeyword) : true);
|
||
|
||
// 模拟用户数据(实际应从数据源获取)
|
||
var users = new List<User>
|
||
{
|
||
new User { Name = "张三", Age = 25 },
|
||
new User { Name = "李四", Age = 30 },
|
||
new User { Name = "李白", Age = 29 },
|
||
new User { Name = "王五", Age = 35 }
|
||
};
|
||
|
||
result.Parameters = new object[] { users, condition };
|
||
result.ParamTypes = new[] { "List<User>", "Func<User, Boolean>" };
|
||
break;
|
||
|
||
case "COUNTIF":
|
||
// 提取数值范围(如"5000到20000")和数据
|
||
var rangeMatch = Regex.Match(text, @"(\d+)到(\d+)");
|
||
if (!rangeMatch.Success)
|
||
{
|
||
result.Error = "COUNTIF需要范围条件,如'5000到20000'";
|
||
return result;
|
||
}
|
||
double min = double.Parse(rangeMatch.Groups[1].Value);
|
||
double max = double.Parse(rangeMatch.Groups[2].Value);
|
||
|
||
// 提取销售额数据
|
||
var salesData = Regex.Match(text, @"\[([\d, ]+)\]")
|
||
.Groups[1].Value.Split(',').Select(double.Parse).ToArray();
|
||
|
||
result.Parameters = new object[] { salesData, (Func<double, bool>)(s => s >= min && s <= max) };
|
||
result.ParamTypes = new[] { "Double[]", "Func<Double, Boolean>" };
|
||
break;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
result.Error = $"参数解析失败:{ex.Message}";
|
||
return result;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
static string GetResultString(object result)
|
||
{
|
||
if (result is double[] nums) return string.Join(", ", nums);
|
||
if (result is List<User> users) return string.Join(", ", users.Select(u => $"{u.Name}({u.Age})"));
|
||
if (result is int count) return count.ToString();
|
||
return "未知结果";
|
||
}
|
||
}
|
||
}
|