DEV Community

Cover image for Balancing Complexity: A Tale of Array Includes vs. Negation
Paul Chin Jr.
Paul Chin Jr.

Posted on

Balancing Complexity: A Tale of Array Includes vs. Negation

The Farmer's Robotic Helper

Developers are constantly balancing complexity and flexibility. Imagine you're a farmer with an assortment of fruits: apples, bananas, oranges, and pears. You have a robotic helper which sorts the fruits into two bins, the Regular Bin and the Premium Bin. Apples and bananas can go into both bins, while oranges and pears are exclusive to the Premium Bin. Each morning, the robot picks up a random fruit and needs to decide which bin it should go to.

As the farmer, you're tasked with writing the software that guides the robot's decision-making. You can choose between two main approaches.

The Negation Approach

One way is to code the robot to identify where a fruit cannot go. If the fruit is not an orange and not a pear, it can be placed in the Regular Bin.

if (fruit !== 'orange' && fruit !== 'pear') {
  regularBin.add(fruit);
}
Enter fullscreen mode Exit fullscreen mode

This approach is simple and flexible. To add a new fruit, you simply avoid adding a new condition. However, it's not immediately clear which fruits can go to the Regular Bin - you have to infer this from what they're not. As the farm diversifies its fruits maintaining this function is easier when there are fewer premium fruits being added.

The Array Includes Approach

Alternatively, you can list the fruits that go to each bin in an array, and check if the fruit is in that array.

const regularBinFruits = [ 'apple', 'banana'];

if(regularBinFruits.includes(fruit)){
  regularBin.add(fruit);
}

Enter fullscreen mode Exit fullscreen mode

This approach is more explicit and understandable. It's clear which fruits can go to the Regular Bin. However, it's slightly more complex in terms of code, and adding new fruit requires updating the array. When the farm adds any regular fruit, the farmer has to update the array. When the farm adds premium fruits, no change is needed.

There are other possible solutions to this problem. Here are a couple of them:

  1. Use a dictionary or a map: This approach can be very efficient especially when you have a large number of categories or items. Instead of using an array or a negation logic, you can map each item to a certain value (true/false, or 0/1, or any other meaningful value). This way, you can check the membership of an item in constant time. Here is an example:
let regularBinFruits = { 'apple': true, 'banana': true };

if(regularBinFruits[fruit]){
  regularBin.add(fruit);
}
Enter fullscreen mode Exit fullscreen mode
  1. Use a switch-case structure: This might be a good choice if you have a small number of items and each item requires a different set of actions. However, it can become cumbersome if you have a large number of items.
switch(fruit) {
  case 'apple':
  case 'banana':
    regularBin.add(fruit);
    // break is omitted to allow fallthrough
  case 'orange':
  case 'pear':
    premiumBin.add(fruit);
    break;
  default:
    // handle unknown fruit
    break;
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

At its core, this dilemma of categorizing items -- whether they're fruits for a farmer's robot or variables in a software program -- is a foundational problem in both computer science and mathematics. It deals with set theory, conditional logic, and algorithmic complexity. These subjects are often surrounded by academic jargon that can make them seem daunting.

However, as we've seen through the practical examples in this blog post, these concepts are not as complex as they might initially appear. They're essentially about making decisions based on whether or not certain conditions are met. Do I put this apple in the regular bin or the premium bin, or both?

In each case, we've seen that there are different approaches you can take, each with its own trade-offs. The negation approach is simple and flexible but can be less explicit. The array includes approach is more explicit but slightly more complex and less flexible. Other solutions, like using a map or a switch-case structure, offer their own sets of advantages and disadvantages.

In the end, the best solution always depends on the specific context and requirements of your problem. The key is to understand your use case and choose the solution that best meets your needs. And remember, while these problems can be expressed in academic terms, they're fundamentally about making decisions -- something we all do every day. So don't be intimidated by the jargon. You're more than capable of understanding and applying these concepts.

Top comments (3)

Collapse
 
dominionworkz profile image
Quincy Bulla

Insightful, keep up the work

Collapse
 
pchinjr profile image
Paul Chin Jr.

Appreciate the comment, @dominionworkz ! I'll be writing more posts about programming in general. If you have any suggestions for topics, def let me know.

Collapse
 
dominionworkz profile image
Quincy Bulla

ok, PC, I will be thinking of something