返回顶部
首页 > 资讯 > 精选 >C#模式匹配有哪些及怎么实现
  • 260
分享到

C#模式匹配有哪些及怎么实现

2023-06-29 09:06:28 260人浏览 独家记忆
摘要

这篇文章主要介绍“C#模式匹配有哪些及怎么实现”,在日常操作中,相信很多人在C#模式匹配有哪些及怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#模式匹配有哪些及怎么实现”的疑惑有所帮助!接下来,请跟

这篇文章主要介绍“C#模式匹配有哪些及怎么实现”,在日常操作中,相信很多人在C#模式匹配有哪些及怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#模式匹配有哪些及怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

模式匹配

要使用模式匹配,首先要了解什么是模式。在使用正则表达式匹配字符串时,正则表达式自己就是一个模式,而对字符串使用这段正则表达式进行匹配的过程就是模式匹配。而在代码中也是同样的,我们对对象采用某种模式进行匹配的过程就是模式匹配。

C# 11 支持的模式有很多,包含:

  • 声明模式(declaration pattern)

  • 类型模式(type pattern)

  • 常数模式(constant pattern)

  • 关系模式(relational pattern)

  • 逻辑模式(logical pattern)

  • 属性模式(property pattern)

  • 位置模式(positional pattern)

  • var 模式(var pattern)

  • 丢弃模式(discard pattern)

  • 列表模式(list pattern)

  • 切片模式(slice pattern)

而其中,不少模式都支持递归,也就意味着可以模式嵌套模式,以此来实现更加强大的匹配功能。

模式匹配可以通过 switch 表达式来使用,也可以在普通的 switch 语句中作为 case 使用,还可以在 if 条件中通过 is 来使用。本文主要在 switch 表达式中使用模式匹配。

那么接下来就对这些模式进行介绍。

实例:表达式计算器

为了更直观地介绍模式匹配,我们接下来利用模式匹配来编写一个表达式计算器。

为了编写表达式计算器,首先我们需要对表达式进行抽象:

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public abstract T Eval(params (string Name, T Value)[] args);}

我们用上面这个 Expr<T> 来表示一个表达式,其中 T 是操作数的类型,然后进一步将表达式分为常数表达式 ConstantExpr、参数表达式 ParameterExpr、一元表达式 UnaryExpr、二元表达式 BinaryExpr 和三元表达式 TernaryExpr。最后提供一个 Eval 方法,用来计算表达式的值,该方法可以传入一个 args 来提供表达式计算所需要的参数。

有了一、二元表达式自然也需要运算符,例如加减乘除等,我们也同时定义 Operator 来表示运算符:

public abstract record Operator{    public record UnaryOperator(Operators Operator) : Operator;    public record BinaryOperator(BinaryOperators Operator) : Operator;}

然后设置允许的运算符,其中前三个是一元运算符,后面的是二元运算符:

public enum Operators{    [Description("~")] Inv, [Description("-")] Min, [Description("!")] LogicalNot,    [Description("+")] Add, [Description("-")] Sub, [Description("*")] Mul, [Description("/")] Div,    [Description("&")] And, [Description("|")] Or, [Description("^")] Xor,    [Description("==")] Eq, [Description("!=")] Ne,    [Description(">")] Gt, [Description("<")] Lt, [Description(">=")] Ge, [Description("<=")] Le,    [Description("&&")] LogicalAnd, [Description("||")] LogicalOr,}

你可以能会好奇对 T 的运算能如何实现逻辑与或非,关于这一点,我们直接使用 0 来代表 false,非 0 代表 true

接下来就是分别实现各类表达式的时间!

常数表达式

常数表达式很简单,它保存一个常数值,因此只需要在构造方法中将用户提供的值存储下来。它的 Eval 实现也只需要简单返回存储的值即可:

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public class ConstantExpr : Expr<T>    {        public ConstantExpr(T value) => Value = value;        public T Value { get; }        public void Deconstruct(out T value) => value = Value;        public override T Eval(params (string Name, T Value)[] args) => Value;    }}

参数表达式

参数表达式用来定义表达式计算过程中的参数,允许用户在对表达式执行 Eval 计算结果的时候传参,因此只需要存储参数名。它的 Eval 实现需要根据参数名在 args 中找出对应的参数值:

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public class ParameterExpr : Expr<T>    {        public ParameterExpr(string name) => Name = name;        public string Name { get; }        public void Deconstruct(out string name) => name = Name;        // 对 args 进行模式匹配        public override T Eval(params (string Name, T Value)[] args) => args switch        {            // 如果 args 有至少一个元素,那我们把第一个元素拿出来存为 (name, value),            // 然后判断 name 是否和本参数表达式中存储的参数名 Name 相同。            // 如果相同则返回 value,否则用 args 除去第一个元素剩下的参数继续匹配。            [var (name, value), .. var tail] => name == Name ? value : Eval(tail),            // 如果 args 是空列表,则说明在 args 中没有找到名字和 Name 相同的参数,抛出异常            [] => throw new InvalidOperationException($"Expected an argument named {Name}.")        };    }}

模式匹配会从上往下依次进行匹配,直到匹配成功为止。

上面的代码中你可能会好奇 [var (name, value), .. var tail] 是个什么模式,这个模式整体看是列表模式,并且列表模式内组合使用声明模式、位置模式和切片模式。例如:

  • []:匹配一个空列表。[1, _, 3]:匹配一个长度是 3,并且首尾元素分别是 1、3 的列表。其中 _ 是丢弃模式,表示任意元素。

  • [_, .., 3]:匹配一个末元素是 3,并且 3 不是首元素的列表。其中 .. 是切片模式,表示任意切片。

  • [1, ..var tail]:匹配一个首元素是 1 的列表,并且将除了首元素之外元素的切片赋值给 tail。其中 var tailvar 模式,用于将匹配结果赋值给变量。

  • [var head, ..var tail]:匹配一个列表,将它第一个元素赋值给 head,剩下元素的切片赋值给 tail,这个切片里可以没有元素。

  • [var (name, value), ..var tail]:匹配一个列表,将它第一个元素赋值给 (name, value),剩下元素的切片赋值给 tail,这个切片里可以没有元素。其中 (name, value) 是位置模式,用于将第一个元素的解构结果根据位置分别赋值给 namevalue,也可以写成 (var name, var value)

一元表达式

一元表达式用来处理只有一个操作数的计算,例如非、取反等。

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public class UnaryExpr : Expr<T>    {        public UnaryExpr(UnaryOperator op, Expr<T> expr) => (Op, Expr) = (op, expr);        public UnaryOperator Op { get; }        public Expr<T> Expr { get; }        public void Deconstruct(out UnaryOperator op, out Expr<T> expr) => (op, expr) = (Op, Expr);        // 对 Op 进行模式匹配        public override T Eval(params (string Name, T Value)[] args) => Op switch        {            // 如果 Op 是 UnaryOperator,则将其解构结果赋值给 op,然后对 op 进行匹配,op 是一个枚举,而 .net 中的枚举值都是整数            UnaryOperator(var op) => op switch            {                // 如果 op 是 Operators.Inv                Operators.Inv => ~Expr.Eval(args),                // 如果 op 是 Operators.Min                Operators.Min => -Expr.Eval(args),                // 如果 op 是 Operators.LogicalNot                Operators.LogicalNot => Expr.Eval(args) == T.Zero ? T.One : T.Zero,                // 如果 op 的值大于 LogicalNot 或者小于 0,表示不是一元运算符                > Operators.LogicalNot or < 0 => throw new InvalidOperationException($"Expected an unary operator, but Got {op}.")            },            // 如果 Op 不是 UnaryOperator            _ => throw new InvalidOperationException("Expected an unary operator.")        };    }}

上面的代码中,首先利用了 C# 元组可作为左值的特性,分别使用一行代码就做完了构造方法和解构方法的赋值:(Op, Expr) = (op, expr)(op, expr) = (Op, Expr)。如果你好奇能否利用这个特性交换多个变量,答案是可以!

Eval 中,首先将类型模式、位置模式和声明模式组合成 UnaryOperator(var op),表示匹配 UnaryOperator 类型、并且能解构出一个元素的东西,如果匹配则将解构出来的那个元素赋值给 op

然后我们接着对解构出来的 op 进行匹配,这里用到了常数模式,例如 Operators.Inv 用来匹配 op 是否是 Operators.Inv。常数模式可以使用各种常数对对象进行匹配。

这里的 > Operators.LogicalNot< 0 则是关系模式,分别用于匹配大于 Operators.LogicalNot 的值和小于 0 的指。然后利用逻辑模式 or 将两个模式组合起来表示或的关系。逻辑模式除了 or 之外还有 andnot

由于我们在上面穷举了枚举中所有的一元运算符,因此也可以将 > Operators.LogicalNot or < 0 换成丢弃模式 _ 或者 var 模式 var foo,两者都用来匹配任意的东西,只不过前者匹配到后直接丢弃,而后者声明了个变量 foo 将匹配到的值放到里面:

op switch{    // ...    _ => throw new InvalidOperationException($"Expected an unary operator, but got {op}.")}

op switch{    // ...    var foo => throw new InvalidOperationException($"Expected an unary operator, but got {foo}.")}

二元表达式

二元表达式用来表示操作数有两个的表达式。有了一元表达式的编写经验,二元表达式如法炮制即可。

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public class BinaryExpr : Expr<T>    {        public BinaryExpr(BinaryOperator op, Expr<T> left, Expr<T> right) => (Op, Left, Right) = (op, left, right);        public BinaryOperator Op { get; }        public Expr<T> Left { get; }        public Expr<T> Right { get; }        public void Deconstruct(out BinaryOperator op, out Expr<T> left, out Expr<T> right) => (op, left, right) = (Op, Left, Right);        public override T Eval(params (string Name, T Value)[] args) => Op switch        {            BinaryOperator(var op) => op switch            {                Operators.Add => Left.Eval(args) + Right.Eval(args),                Operators.Sub => Left.Eval(args) - Right.Eval(args),                Operators.Mul => Left.Eval(args) * Right.Eval(args),                Operators.Div => Left.Eval(args) / Right.Eval(args),                Operators.And => Left.Eval(args) & Right.Eval(args),                Operators.Or => Left.Eval(args) | Right.Eval(args),                Operators.Xor => Left.Eval(args) ^ Right.Eval(args),                Operators.Eq => Left.Eval(args) == Right.Eval(args) ? T.One : T.Zero,                Operators.Ne => Left.Eval(args) != Right.Eval(args) ? T.One : T.Zero,                Operators.Gt => Left.Eval(args) > Right.Eval(args) ? T.One : T.Zero,                Operators.Lt => Left.Eval(args) < Right.Eval(args) ? T.One : T.Zero,                Operators.Ge => Left.Eval(args) >= Right.Eval(args) ? T.One : T.Zero,                Operators.Le => Left.Eval(args) <= Right.Eval(args) ? T.One : T.Zero,                Operators.LogicalAnd => Left.Eval(args) == T.Zero || Right.Eval(args) == T.Zero ? T.Zero : T.One,                Operators.LogicalOr => Left.Eval(args) == T.Zero && Right.Eval(args) == T.Zero ? T.Zero : T.One,                < Operators.Add or > Operators.LogicalOr => throw new InvalidOperationException($"Unexpected a binary operator, but got {op}.")            },            _ => throw new InvalidOperationException("Unexpected a binary operator.")        };    }}

同理,也可以将 < Operators.Add or > Operators.LogicalOr 换成丢弃模式或者 var 模式。

三元表达式

三元表达式包含三个操作数:条件表达式 Cond、为真的表达式 Left、为假的表达式 Right。该表达式中会根据 Cond 是否为真来选择取 Left 还是 Right,实现起来较为简单:

public abstract partial class Expr<T> where T : IBinaryNumber<T>{    public class TernaryExpr : Expr<T>    {        public TernaryExpr(Expr<T> cond, Expr<T> left, Expr<T> right) => (Cond, Left, Right) = (cond, left, right);        public Expr<T> Cond { get; }        public Expr<T> Left { get; }        public Expr<T> Right { get; }        public void Deconstruct(out Expr<T> cond, out Expr<T> left, out Expr<T> right) => (cond, left, right) = (Cond, Left, Right);        public override T Eval(params (string Name, T Value)[] args) => Cond.Eval(args) == T.Zero ? Right.Eval(args) : Left.Eval(args);    }}

完成。我们用了仅仅几十行代码就完成了全部的核心逻辑!这便是模式匹配的强大之处:简洁、直观且高效。

表达式判等

至此为止,我们已经完成了所有的表达式构造、解构和计算的实现。接下来我们为每一个表达式实现判等逻辑,即判断两个表达式(字面上)是否相同。

例如 a == b ? 2 : 4a == b ? 2 : 5 不相同,a == b ? 2 : 4c == d ? 2 : 4 不相同,而 a == b ? 2 : 4a == b ? 2 : 4 相同。

为了实现该功能,我们重写每一个表达式的 EqualsGetHashCode 方法。

常数表达式

常数表达式判等只需要判断常数值是否相等即可:

public override bool Equals(object? obj) => obj is ConstantExpr(var value) && value == Value;public override int GetHashCode() => Value.GetHashCode();
参数表达式

参数表达式判等只需要判断参数名是否相等即可:

public override bool Equals(object? obj) => obj is ParameterExpr(var name) && name == Name;public override int GetHashCode() => Name.GetHashCode();
一元表达式

一元表达式判等,需要判断被比较的表达式是否是一元表达式,如果也是的话则判断运算符和操作数是否相等:

public override bool Equals(object? obj) => obj is UnaryExpr({ Operator: var op }, var expr) && (op, expr).Equals((Op.Operator, Expr));public override int GetHashCode() => (Op, Expr).GetHashCode();

上面的代码中用到了属性模式 { Operator: var op },用来匹配属性的值,这里直接组合了声明模式将属性 Operator 的值赋值给了 expr。另外,C# 中的元组可以组合起来进行判等操作,因此不需要写 op.Equals(Op.Operator) && expr.Equals(Expr),而是可以直接写 (op, expr).Equals((Op.Operator, Expr))

二元表达式

和一元表达式差不多,区别在于这次多了一个操作数:

public override bool Equals(object? obj) => obj is BinaryExpr({ Operator: var op }, var left, var right) && (op, left, right).Equals((Op.Operator, Left, Right));public override int GetHashCode() => (Op, Left, Right).GetHashCode();
三元表达式

和二元表达式差不多,只不过运算符 Op 变成了操作数 Cond

public override bool Equals(object? obj) => obj is TernaryExpr(var cond, var left, var right) && cond.Equals(Cond) && left.Equals(Left) && right.Equals(Right);public override int GetHashCode() => (Cond, Left, Right).GetHashCode();

到此为止,我们为所有的表达式都实现了判等。

一些工具方法

我们重载一些 Expr<T> 的运算符方便我们使用:

public static Expr<T> operator ~(Expr<T> operand) => new UnaryExpr(new(Operators.Inv), operand);public static Expr<T> operator !(Expr<T> operand) => new UnaryExpr(new(Operators.LogicalNot), operand);public static Expr<T> operator -(Expr<T> operand) => new UnaryExpr(new(Operators.Min), operand);public static Expr<T> operator +(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Add), left, right);public static Expr<T> operator -(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Sub), left, right);public static Expr<T> operator *(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Mul), left, right);public static Expr<T> operator /(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Div), left, right);public static Expr<T> operator &(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.And), left, right);public static Expr<T> operator |(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Or), left, right);public static Expr<T> operator ^(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Xor), left, right);public static Expr<T> operator >(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Gt), left, right);public static Expr<T> operator <(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Lt), left, right);public static Expr<T> operator >=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Ge), left, right);public static Expr<T> operator <=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Le), left, right);public static Expr<T> operator ==(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Eq), left, right);public static Expr<T> operator !=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Ne), left, right);public static implicit operator Expr<T>(T value) => new ConstantExpr(value);public static implicit operator Expr<T>(string name) => new ParameterExpr(name);public static implicit operator Expr<T>(bool value) => new ConstantExpr(value ? T.One : T.Zero);public override bool Equals(object? obj) => base.Equals(obj);public override int GetHashCode() => base.GetHashCode();

由于重载了 ==!=,编译器为了保险起见提示我们重写 EqualsGetHashCode,这里实际上并不需要重写,因此直接调用 base 上的方法保持默认行为即可。

然后编写两个扩展方法用来方便构造三元表达式,和从 Description 中获取运算符的名字:

public static class Extensions{    public static Expr<T> Switch<T>(this Expr<T> cond, Expr<T> left, Expr<T> right) where T : IBinaryNumber<T> => new Expr<T>.TernaryExpr(cond, left, right);    public static string? GetName<T>(this T op) where T : Enum => typeof(T).GetMember(op.ToString()).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()?.Description;}

由于有参数表达式参与时需要我们提前提供参数值才能调用 Eval 进行计算,因此我们写一个交互式的 Eval 来在计算过程中遇到参数表达式时提示用户输入值,起名叫做 InteractiveEval

public T InteractiveEval(){    var names = Array.Empty<string>();    return Eval(GetArgs(this, ref names, ref names));}private static T GetArg(string name, ref string[] names){    Console.Write($"Parameter {name}: ");    string? str;    do { str = Console.ReadLine(); }    while (str is null);    names = names.Append(name).ToArray();    return T.Parse(str, NumberStyles.Number, null);}private static (string Name, T Value)[] GetArgs(Expr<T> expr, ref string[] assigned, ref string[] filter) => expr switch{    TernaryExpr(var cond, var left, var right) => GetArgs(cond, ref assigned, ref assigned).Concat(GetArgs(left, ref assigned,ref assigned)).Concat(GetArgs(right, ref assigned, ref assigned)).ToArray(),    BinaryExpr(_, var left, var right) => GetArgs(left, ref assigned, ref assigned).Concat(GetArgs(right, ref assigned, refassigned)).ToArray(),    UnaryExpr(_, var uexpr) => GetArgs(uexpr, ref assigned, ref assigned),    ParameterExpr(var name) => filter switch    {        [var head, ..] when head == name => Array.Empty<(string Name, T Value)>(),        [_, .. var tail] => GetArgs(expr, ref assigned, ref tail),        [] => new[] { (name, GetArg(name, ref assigned)) }    },    _ => Array.Empty<(string Name, T Value)>()};

这里在 GetArgs 方法中,模式 [var head, ..] 后面跟了一个 when head == name,这里的 when 用来给模式匹配指定额外的条件,仅当条件满足时才匹配成功,因此 [var head, ..] when head == name 的含义是,匹配至少含有一个元素的列表,并且将头元素赋值给 head,且仅当 head == name 时匹配才算成功。

最后我们再重写 ToString 方法方便输出表达式,就全部大功告成了。

测试

接下来让我测试测试我们编写的表达式计算器:

Expr<int> a = 4;Expr<int> b = -3;Expr<int> x = "x";Expr<int> c = !((a + b) * (a - b) > x);Expr<int> y = "y";Expr<int> z = "z";Expr<int> expr = (c.Switch(y, z) - a > x).Switch(z + a, y / b);Console.WriteLine(expr);Console.WriteLine(expr.InteractiveEval());

运行后得到输出:

((((! ((((4) + (-3)) * ((4) - (-3))) > (x))) ? (y) : (z)) - (4)) > (x)) ? ((z) + (4)) : ((y) / (-3))

然后我们给 xyz 分别设置成 42、27 和 35,即可得到运算结果:

Parameter x: 42
Parameter y: 27
Parameter z: 35
-9

再测测表达式判等逻辑:

Expr<int> expr1, expr2, expr3;{    Expr<int> a = 4;    Expr<int> b = -3;    Expr<int> x = "x";    Expr<int> c = !((a + b) * (a - b) > x);    Expr<int> y = "y";    Expr<int> z = "z";    expr1 = (c.Switch(y, z) - a > x).Switch(z + a, y / b);}{    Expr<int> a = 4;    Expr<int> b = -3;    Expr<int> x = "x";    Expr<int> c = !((a + b) * (a - b) > x);    Expr<int> y = "y";    Expr<int> z = "z";    expr2 = (c.Switch(y, z) - a > x).Switch(z + a, y / b);}{    Expr<int> a = 4;    Expr<int> b = -3;    Expr<int> x = "x";    Expr<int> c = !((a + b) * (a - b) > x);    Expr<int> y = "y";    Expr<int> w = "w";    expr3 = (c.Switch(y, w) - a > x).Switch(w + a, y / b);}Console.WriteLine(expr1.Equals(expr2));Console.WriteLine(expr1.Equals(expr3));

得到输出:

True
False

活动模式

在未来,C# 将会引入活动模式,该模式允许用户自定义模式匹配的方法,例如:

static bool Even<T>(this T value) where T : IBinaryInteger<T> => value % 2 == 0;

上述代码定义了一个 T 的扩展方法 Even,用来匹配 value 是否为偶数,于是我们便可以这么使用:

var x = 3;var y = x switch{    Even() => "even",    _ => "odd"};

此外,该模式还可以和解构模式结合,允许用户自定义解构行为,例如:

static bool Int(this string value, out int result) => int.TryParse(value, out result);

然后使用的时候:

var x = "3";var y = x switch{    Int(var result) => result,    _ => 0};

即可对 x 这个字符串进行匹配,如果 x 可以被解析为 int,就取解析结果 result,否则取 0。

到此,关于“C#模式匹配有哪些及怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C#模式匹配有哪些及怎么实现

本文链接: https://lsjlt.com/news/323982.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C#模式匹配有哪些及怎么实现
    这篇文章主要介绍“C#模式匹配有哪些及怎么实现”,在日常操作中,相信很多人在C#模式匹配有哪些及怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#模式匹配有哪些及怎么实现”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-29
  • SqlServer2016模糊匹配的方式有哪些
    这篇文章主要介绍SqlServer2016模糊匹配的方式有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体如下:数据库是Sqlserver 2016版现在业务需求是:要查询出企...
    99+
    2024-04-02
  • Beam中的模式匹配怎么实现
    在Beam中,模式匹配可以通过使用Match和Case来实现。Match用于指定要匹配的值,Case用于定义匹配的模式和对应的处理逻...
    99+
    2024-04-02
  • MySQL中有哪些字符串匹配模式
    这期内容当中小编将会给大家带来有关MySQL中有哪些字符串匹配模式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。  MySQL字符串匹配模式有哪些  SQL的模式匹配允许...
    99+
    2024-04-02
  • vue路由模式有哪些及怎么实现
    本篇内容介绍了“vue路由模式有哪些及怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!vue路由模式有:1、hash模式,使用URL的...
    99+
    2023-07-04
  • C语言中如何实现模式匹配
    这篇文章主要介绍了C语言中如何实现模式匹配的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中如何实现模式匹配文章都会有所收获,下面我们一起来看看吧。C语言数据结构中串的模式匹配串的模式匹配问题:朴素算法与K...
    99+
    2023-06-16
  • C语言中怎么实现朴素模式匹配算法
    这篇文章主要介绍“C语言中怎么实现朴素模式匹配算法”,在日常操作中,相信很多人在C语言中怎么实现朴素模式匹配算法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言中怎么实现朴素模式匹配算法”的疑惑有所帮助!...
    99+
    2023-06-08
  • c++单例模式的实现方式有哪些
    在C++中,可以通过以下几种方式来实现单例模式: 饿汉式单例模式(Eager Initialization): 在类定义中静态地创...
    99+
    2024-02-29
    c++
  • Python+FuzzyWuzzy怎么实现模糊匹配
    今天小编给大家分享一下Python+FuzzyWuzzy怎么实现模糊匹配的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1. ...
    99+
    2023-06-30
  • opencv C++模板匹配的简单实现
    目录一简单实现二函数及原理讲解1matchTemplate()参数详解2minMaxLoc()函数一 简单实现 #include <opencv2/opencv.hpp>...
    99+
    2024-04-02
  • opencv C++模板匹配的实现方法
    这篇文章主要介绍“opencv C++模板匹配的实现方法”,在日常操作中,相信很多人在opencv C++模板匹配的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”opencv&nb...
    99+
    2023-06-29
  • C++中有哪些实现单例模式的方式
    这篇文章将为大家详细讲解有关C++中有哪些实现单例模式的方式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C++单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点,但...
    99+
    2023-06-17
  • PHP中使用Redis实现模式匹配
    在 web 开发中,Redis 已经成为了非常流行的缓存和数据库,而 PHP 也是广泛使用的 web 开发语言。结合这两者,我们可以在 PHP 中使用 Redis 来实现模式匹配的功能,极大地提高了网站的性能和用户体验。Redis 是一款基...
    99+
    2023-05-15
    PHP redis 模式匹配
  • PHP中常见的开发模式有哪些及怎么实现
    这篇文章主要介绍“PHP中常见的开发模式有哪些及怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“PHP中常见的开发模式有哪些及怎么实现”文章能帮助大家解决问题。设计模式六大原则开放封闭原则:一...
    99+
    2023-07-04
  • Python实现字符串模糊匹配方式
    目录Python字符串模糊匹配包含四个参数python-re模块,模糊匹配Python字符串模糊匹配 Python的difflib库中get_close_matches方法 包含四个...
    99+
    2024-04-02
  • Python OpenCV怎么实现图像模板匹配
    今天小编给大家分享一下Python OpenCV怎么实现图像模板匹配的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。...
    99+
    2023-06-29
  • C++实现LeetCode(10.正则表达式匹配)
    [LeetCode] 10. Regular Expression Matching 正则表达式匹配 Given an input string (s) and a pattern ...
    99+
    2024-04-02
  • Python中正则表达式及其常用匹配函数有哪些
    这篇文章主要介绍Python中正则表达式及其常用匹配函数有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。/简介/Python 自1...
    99+
    2023-06-01
  • C#特殊字符的匹配怎么实现
    本篇内容主要讲解“C#特殊字符的匹配怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#特殊字符的匹配怎么实现”吧!下面提供一些简单的C#正则表达式之特殊字符的匹配示例:string&nb...
    99+
    2023-06-17
  • pampy超强的模式匹配工具的实现
    目录何为模式匹配下载pampy栗子单个字符匹配匹配开头和结尾匹配字典的key使用特性1: HEAD 和 TAIL特性2:甚至能匹配字典中的键特性3: 搭配正则何为模式匹配 模式匹配...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作