logical operators
programming tips
conditional statements
code optimization
software development

How to shorten multiple condition

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Long chains of && or || conditions reduce readability and increase the chance of logic errors. Most languages provide patterns to shorten them: arrays with .includes() or in, early returns, lookup tables, and bit flags. The goal is not fewer characters but clearer intent — a reader should immediately understand what the condition checks. This article shows practical techniques in JavaScript, Python, Java, and C#.

JavaScript: Array.includes()

javascript
1// Before — repetitive OR checks
2if (status === 'active' || status === 'pending' || status === 'review' || status === 'approved') {
3    processItem();
4}
5
6// After — array includes
7if (['active', 'pending', 'review', 'approved'].includes(status)) {
8    processItem();
9}
10
11// For AND conditions — use .every()
12const checks = [isValid, isActive, hasPermission, !isExpired];
13if (checks.every(Boolean)) {
14    processItem();
15}
16
17// For OR conditions — use .some()
18const warnings = [isExpired, isOverBudget, hasErrors];
19if (warnings.some(Boolean)) {
20    showWarning();
21}

.includes() replaces repeated === checks with a single readable expression. .every() and .some() generalize AND/OR over arrays of booleans.

Python: in and all/any

python
1# Before
2if color == 'red' or color == 'green' or color == 'blue':
3    process(color)
4
5# After — tuple membership test
6if color in ('red', 'green', 'blue'):
7    process(color)
8
9# AND conditions with all()
10conditions = [user.is_active, user.has_permission, not user.is_banned]
11if all(conditions):
12    grant_access()
13
14# OR conditions with any()
15errors = [form.has_error('email'), form.has_error('name'), form.has_error('phone')]
16if any(errors):
17    show_form_errors()
18
19# Range check shorthand
20# Before
21if age >= 18 and age <= 65:
22    eligible = True
23
24# After — chained comparison
25if 18 <= age <= 65:
26    eligible = True

Python's in operator works with tuples, lists, and sets. Use a set for large collections (O(1) lookup). Chained comparisons like 18 <= age <= 65 are unique to Python and very readable.

Java: Set.contains() and EnumSet

java
1// Before
2if (status.equals("active") || status.equals("pending") || status.equals("review")) {
3    process();
4}
5
6// After — Set.of (Java 9+)
7if (Set.of("active", "pending", "review").contains(status)) {
8    process();
9}
10
11// With enums — EnumSet
12enum Status { ACTIVE, PENDING, REVIEW, CLOSED }
13
14EnumSet<Status> processable = EnumSet.of(Status.ACTIVE, Status.PENDING, Status.REVIEW);
15if (processable.contains(currentStatus)) {
16    process();
17}
18
19// Multiple AND conditions — extract to methods
20if (isEligible(user)) {
21    grantAccess(user);
22}
23
24private boolean isEligible(User user) {
25    return user.isActive()
26        && user.hasPermission()
27        && !user.isBanned()
28        && user.getAge() >= 18;
29}

Set.of() creates an immutable set for clean membership tests. EnumSet is optimized for enum types and uses bit vectors internally.

C#: Contains and Pattern Matching

csharp
1// Before
2if (day == "Monday" || day == "Wednesday" || day == "Friday")
3    GoToGym();
4
5// After — HashSet or array Contains
6if (new[] { "Monday", "Wednesday", "Friday" }.Contains(day))
7    GoToGym();
8
9// C# 9+ pattern matching with or
10if (statusCode is 200 or 201 or 204)
11    HandleSuccess();
12
13// C# 9+ relational patterns
14if (score is >= 90 and <= 100)
15    grade = "A";
16
17// Switch expression for multiple conditions
18string category = age switch
19{
20    < 13  => "child",
21    < 18  => "teen",
22    < 65  => "adult",
23    _     => "senior"
24};

C# 9 introduced is ... or and is ... and patterns, which are the most concise syntax for multi-value or range checks.

Early Return / Guard Clauses

javascript
1// Before — deeply nested
2function processOrder(order) {
3    if (order) {
4        if (order.isValid) {
5            if (order.items.length > 0) {
6                if (!order.isCancelled) {
7                    // actual logic
8                    submitOrder(order);
9                }
10            }
11        }
12    }
13}
14
15// After — guard clauses
16function processOrder(order) {
17    if (!order) return;
18    if (!order.isValid) return;
19    if (order.items.length === 0) return;
20    if (order.isCancelled) return;
21
22    submitOrder(order);
23}

Guard clauses flatten nested conditions by returning early for invalid cases. The main logic sits at the top level, making it immediately visible.

Lookup Tables

javascript
1// Before — long if/else chain
2function getDiscount(tier) {
3    if (tier === 'bronze') return 0.05;
4    if (tier === 'silver') return 0.10;
5    if (tier === 'gold') return 0.15;
6    if (tier === 'platinum') return 0.20;
7    return 0;
8}
9
10// After — lookup table
11const discounts = {
12    bronze: 0.05,
13    silver: 0.10,
14    gold: 0.15,
15    platinum: 0.20,
16};
17
18function getDiscount(tier) {
19    return discounts[tier] ?? 0;
20}

Lookup tables replace conditional branches with data. They are easier to maintain, extend, and test than long if/else or switch chains.

Common Pitfalls

  • Creating arrays inside hot loops: ['a', 'b', 'c'].includes(x) allocates a new array every call. For performance-critical loops, define the array as a constant outside the loop or use a Set.
  • Losing short-circuit evaluation: [fn1(), fn2(), fn3()].every(Boolean) evaluates all functions upfront. Unlike fn1() && fn2() && fn3(), there is no short-circuit — all three run even if the first returns false.
  • Using == instead of === with includes: In JavaScript, [0].includes(false) returns false (strict equality), which is correct. But manual checks with == would match 0 == false as true. .includes uses strict comparison.
  • Readability over brevity: Compressing conditions into a single clever expression can be harder to understand than a few clear lines. Optimize for the reader, not the character count.
  • Forgetting the default case: Lookup tables and switch expressions need a fallback for unexpected values. Always include a default case or nullish coalescing (?? defaultValue).

Summary

  • Replace repeated ===/== checks with .includes() (JS), in (Python), Set.of().contains() (Java), or is ... or (C# 9)
  • Use .every()/all() for AND chains and .some()/any() for OR chains
  • Use guard clauses (early returns) to flatten deeply nested conditions
  • Use lookup tables (objects/maps/dicts) to replace long if/else or switch chains
  • Prioritize readability — the goal is clearer intent, not fewer characters

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.