Simplify multiple if statements that use if (string.contains())

假如想象 提交于 2019-12-04 06:05:08

问题


I am working on a personal assistant program and I have a method called input_parse() which looks at the input string and checks for words that correspond to "commands" the pseudo code looks like this.

if (input.contains("argA")
   {//execute command A}
if (input.contains("argB") && input.contains("argC"))
   {//execute command B}

is there a simpler way to tackle this problem perhaps with a string array of commands and then use a switch statement for the commands based on the index of the argument?


回答1:


You can create a Dictionary where the value will be your command and the key can be your string (arg name).

var myCommands = new Dictionary<string, Action>();
myCommands.Add("argA", new Action(() => Console.WriteLine("arga was passed")));
myCommands.Add("argB", new Action(() => Console.WriteLine("argb was passed")));

Than you can invoke your commands iterating through the keys of the dictionary. So if both argA and argB are passed both commands will be invoked.

foreach (var key in myCommands.Keys)
{
  if (input.Contains(key))
  {
    myCommands[key]();
  }
}

This is the easiest way, you don't need to create any class structure or anything like that. Perfect for simple console app.

EDIT

To cross match the parameters you can have the following Dictionary defined.

var myCommands new Dictionary<Func<string, bool>, Action>>();
myCommands.Add(new Func<string, bool>(i => i.Contains("argA")),new Action(() => Console.WriteLine("arga was passed"));
myCommands.Add(new Func<string, bool>(i => i.Contains("argB")),new Action(() => Console.WriteLine("arga was passed"));
myCommands.Add(new Func<string, bool>(i => i.Contains("argB") && e.Contains("argA")),new Action(() => Console.WriteLine("arga & argb was passed"));



foreach (var key in myCommands.Keys)
{
   if (key(input))
   {
      myCommands[key]();
   }
}



回答2:


You have commands and input arguments which are related to each other. It seems logical to me to encapsulate these two things into one object and keep them close. You can create interface for such objects

public interface ICommand
{
    bool CanGetArgumentsFrom(string input);
    void Execute();
}

And commands which implement it

public class CommandA : ICommand
{
    public bool CanGetArgumentsFrom(string input)
    {
        return input.Contains("argA");
    }

    public void Execute()
    {
        /* execute command A */
    }
}

And second command

public class CommandB : ICommand
{
    public bool CanGetArgumentsFrom(string input)
    {
        return input.Contains("argB") && input.Contains("argC");
    }

    public void Execute()
    {
        /* execute command B */
    }
}

Usage is pretty readable

ICommand[] commands = { new CommandA(), new CommandB() };

foreach(var command in commands)
   if (command.CanGetArgumentsFrom(input))
       command.Execute();

You even can have method

public bool TryExecuteCommand(string input)
{
    if (!CanGetArgumentsFrom(input))
        return false;

    Execute();
    return true;
}

Then execution will be even more simple and readable:

foreach(var command in commands)
    command.TryExecute(input);

If you don't want to create named commands, then you can use object which verifies input and executes some action if all required arguments are in place

public class Command
{
    string[] arguments;
    Action action;

    public Command(Action action, params string[] arguments)
    {
        this.action = action;
        this.arguments = arguments;
    }

    public bool TryExecute(string input)
    {
        if (!arguments.All(input.Contains))
            return false;

        action();
        return true;
    }
}

Now with this single class you can create commands:

var commands = new Command[] {
    new Command(_ => /* execute A */, "argA"),
    new Command(_ => /* execute B */, "argB", "argC"),
};



回答3:


You can use IEnumerable.Any (for "or" conditions") or IEnumerable.All (for "and" conditions):

if (input.contains("argA"))
   {//execute command A}
if (new[] { "argB", "argC" }.All(input.Contains))
   {//execute command B}


来源:https://stackoverflow.com/questions/23498628/simplify-multiple-if-statements-that-use-if-string-contains

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!