Home > Software engineering >  Better way for if-else condition with combination of two variables in the set
Better way for if-else condition with combination of two variables in the set

Time:01-11

I have a set of object, each time I will get two objects in the set and do something according to the combination of two object.

the sample will like:

List list = ["A", "B"]

if(list.contains("A") && list.contains("B")){
    decision1()
}
else if(list.contains("A") && list.contains("C")){
    decision2()
}
else if(list.contains("A") && list.contains("D")){
    decision2()

}
else if(list.contains("B") && list.contains("C")){
    decision3()
}
else if(list.contains("B") && list.contains("D")){
    decision1()
}
else if(list.contains("C") && list.contains("D")){
    decision3()

}

I used if-else to consider all combination case but now I have 7 types in the set that says I need to write 21 if-else condition to include all possible combination. since there only have 4 decisions.

Is there any better design to refactor?

CodePudding user response:

I don't know C#, but maybe this python code can give you a little inspiration

from itertools import combinations

a = [i for i in "ABC"]
b = {1: [('A', 'B'), ('B', 'C')], 2: [('A', 'C')]}
for e in combinations(a, 2):
    if e in b[1]:
        print(e, "decision1")
    elif e in b[2]:
        print(e, "decision2")

CodePudding user response:

Why don't we extract these rules into a collection? In case of c# it can be a List<T>:

// readonly IReadOnlyList<...> to prevent from unwanted (occasional) changing
private static readonly IReadOnlyList<(string[] contains, Action action)> rules = 
  new List<(string[] contains, Action action)>() {
    (new string[] { "A", "B" }, () => decision1()),
    (new string[] { "A", "C" }, () => decision2()),
    (new string[] { "A", "D" }, () => decision2()), 
    (new string[] { "B", "C" }, () => decision3()), 
    (new string[] { "B", "D" }, () => decision1()), 
    (new string[] { "C", "D" }, () => decision3()), 
    // Add more rules here
  };

and then we can easily test these rules with a help of Linq:

using System.Linq;

...

rules
  .FirstOrDefault(rule => rule.contains.All(item => list.Contains(item)), 
                                            (null, () => {}))
  .action();

CodePudding user response:

Guessing you want to check always in combination for your first and second list. Therefore I am naming them list1 and list2. Probably there is a way to work also with switches but my recommendation would be to group them in a nested way.

List list1 = ["A", "B", "C", "D"]
List list2 = ["A", "B"]

if (list1.contains("A")) {
    if(list2.contains("B")) {decision1()}
    else if (list2.contains("C") || list2.contains("D")) {decision2()}
    else { /* do nothing */}
}
else if (list1.contains("B")) {
    if(list2.contains("C")) {decision3()}
    else if (list2.contains("D")) {decision1()}
    else { /* do nothing */}
}
else if (list1.contains("C")) {
    if(list2.contains("D")) {decision3()}
    else { /* do nothing */}
}
  • Related