PowerShellUtils/Commands/Fuzzy/SelectFuzzyCommand.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using FuzzySharp;
using PowerShellStandardModule1.Models;
 
namespace PowerShellStandardModule1.Commands.Fuzzy;
 
using FuzzyFunc = Func<string, string, int>;
 
public enum FuzzyStrategy
{
    PartialRatio,
    PartialTokenAbbreviationRatio,
    PartialTokenDifferenceRatio,
    PartialTokenInitialismRatio,
    PartialTokenSetRatio,
    PartialTokenSortRatio,
    Ratio,
    TokenAbbreviationRatio,
    TokenDifferenceRatio,
    TokenInitialismRatio,
    TokenSetRatio,
    TokenSortRatio,
    WeightedRatio
}
 
[Cmdlet(VerbsCommon.Select, "Fuzzy")]
[Alias("Fuzzy")]
[OutputType(typeof(FuzzyResult))]
public class SelectFuzzyCommand : PSCmdlet
{
    [Parameter(
        Mandatory = true,
        Position = 0,
        ValueFromPipeline = true,
        ValueFromPipelineByPropertyName = true,
        HelpMessage = "The first string to compare."
    )]
    public required string String1;
 
    [Parameter(
        Mandatory = true,
        Position = 1,
        ValueFromPipeline = true,
        ValueFromPipelineByPropertyName = true,
        HelpMessage = "The second string to compare."
    )]
    public required string String2;
 
    [Parameter(
        Position = 2, HelpMessage = """
                                    Strategy to use for fuzzy matching. Defaults to 'Ratio'.
                                    Options: "PartialRatio", "PartialTokenAbbreviationRatio", "PartialTokenDifferenceRatio",
                                    "PartialTokenInitialismRatio", "PartialTokenSetRatio", "PartialTokenSortRatio", "Ratio",
                                    "TokenAbbreviationRatio", "TokenDifferenceRatio", "TokenInitialismRatio", "TokenSetRatio", "TokenSortRatio",
                                    "WeightedRatio"
                                    """
    )]
    public FuzzyStrategy Strategy = FuzzyStrategy.Ratio;
 
 
    protected override void ProcessRecord()
    {
        var res = Run();
        WriteObject(res);
    }
 
    public FuzzyResult Run()
    {
        var score = FuzzyFuncs
           .GetValueOrDefault(Strategy, Fuzz.Ratio)(String1, String2);
        return new FuzzyResult(String1, String2, score);
    }
 
    public static FuzzyFunc GetFuzzyStrategy(string strategy)
    {
 
        var arity = typeof(FuzzyFunc)
           .GetMethod("Invoke")!
           .GetParameters()
           .Length;
 
 
        var res = typeof(Fuzz)
               .GetMethods()
               .Where(x => x.IsStatic)
               .Where(
                    x => x.GetParameters()
                           .Length ==
                        arity
                )
               .FirstOrDefault(x => string.Equals(x.Name, strategy, StringComparison.InvariantCultureIgnoreCase))
             ?
            .CreateDelegate(typeof(FuzzyFunc)) ??
            throw new ArgumentException($"Invalid strategy: {strategy}");
 
        return (FuzzyFunc)res;
    }
 
    public static Dictionary<FuzzyStrategy, FuzzyFunc> FuzzyFuncs = typeof(Fuzz)
       .GetMethods()
       .Where(x => x.IsStatic)
       .Where(
            x => x.GetParameters()
                   .Length ==
                2
        )
       .Where(x => x.Name.Contains("ratio", StringComparison.OrdinalIgnoreCase))
       .DistinctBy(x => x.Name)
       .Select(x => KeyValuePair.Create(Enum.Parse<FuzzyStrategy>(x.Name), x.CreateDelegate<FuzzyFunc>()))
       .ToDictionary();
}