Difficulty: Easy | Acceptance: 76.00% | Paid: No Topics: N/A
Implement a class that supports method chaining. The class should have methods that modify internal state and return the object itself, allowing multiple methods to be called in a single statement.
Create a class with the following methods:
add(value)- adds the given value to the current resultsubtract(value)- subtracts the given value from the current resultmultiply(value)- multiplies the current result by the given valuedivide(value)- divides the current result by the given valuegetResult()- returns the current result
Each method (except getResult) should return the object itself to enable chaining.
Table of Contents
- Examples
- Constraints
- Approach 1: Standard Method Chaining
- Approach 2: Builder Pattern
- Approach 3: Functional Approach
Examples
Example 1
Input:
DataFrame animals:
+----------+---------+-----+--------+
| name | species | age | weight |
+----------+---------+-----+--------+
| Tatiana | Snake | 98 | 464 |
| Khaled | Giraffe | 50 | 41 |
| Alex | Leopard | 6 | 328 |
| Jonathan | Monkey | 45 | 463 |
| Stefan | Bear | 100 | 50 |
| Tommy | Panda | 26 | 349 |
+----------+---------+-----+--------+
Output:
+----------+
| name |
+----------+
| Tatiana |
| Jonathan |
| Tommy |
| Alex |
+----------+
Explanation: All animals weighing more than 100 should be included in the results table. Tatiana’s weight is 464, Jonathan’s weight is 463, Tommy’s weight is 349, and Alex’s weight is 328. The results should be sorted in descending order of weight.
Constraints
- 0 <= value <= 100
- The result will always fit in a 32-bit signed integer
- At most 100 operations will be performed
Approach 1: Standard Method Chaining
Intuition
Store the current result in an instance variable and return this from each method to enable chaining.
Steps
- Initialize the result to 0 in the constructor
- For each operation method, modify the result and return
this - The getResult method simply returns the current result
class Calculator:
def __init__(self):
self.result = 0
def add(self, value: int) -> 'Calculator':
self.result += value
return self
def subtract(self, value: int) -> 'Calculator':
self.result -= value
return self
def multiply(self, value: int) -> 'Calculator':
self.result *= value
return self
def divide(self, value: int) -> 'Calculator':
self.result //= value
return self
def getResult(self) -> int:
return self.result
Complexity
- Time: O(1) for each operation
- Space: O(1)
- Notes: Simple and efficient, standard approach for method chaining
Approach 2: Builder Pattern
Intuition Use a separate builder class to construct the calculation step by step, then execute to get the result.
Steps
- Create a Calculator class with a nested Builder
- The Builder stores operations in a list
- Execute runs all operations and returns the final result
from typing import List, Callable
class Calculator:
def __init__(self):
self.result = 0
self.operations: List[Callable[[int], int]] = []
def add(self, value: int) -> 'Calculator':
self.operations.append(lambda x: x + value)
self._apply_operations()
return self
def subtract(self, value: int) -> 'Calculator':
self.operations.append(lambda x: x - value)
self._apply_operations()
return self
def multiply(self, value: int) -> 'Calculator':
self.operations.append(lambda x: x * value)
self._apply_operations()
return self
def divide(self, value: int) -> 'Calculator':
self.operations.append(lambda x: x // value)
self._apply_operations()
return self
def _apply_operations(self):
for op in self.operations:
self.result = op(self.result)
self.operations.clear()
def getResult(self) -> int:
return self.result
Complexity
- Time: O(1) for each operation
- Space: O(1) - operations list is cleared after each call
- Notes: More complex than standard approach, useful for deferred execution
Approach 3: Functional Approach
Intuition Create immutable objects where each operation returns a new Calculator instance with the updated result.
Steps
- Store result as an immutable property
- Each operation creates a new Calculator with the updated result
- This approach is more functional but less memory efficient
from dataclasses import dataclass
@dataclass
class Calculator:
result: int = 0
def add(self, value: int) -> 'Calculator':
return Calculator(self.result + value)
def subtract(self, value: int) -> 'Calculator':
return Calculator(self.result - value)
def multiply(self, value: int) -> 'Calculator':
return Calculator(self.result * value)
def divide(self, value: int) -> 'Calculator':
return Calculator(self.result // value)
def getResult(self) -> int:
return self.result
Complexity
- Time: O(1) for each operation
- Space: O(n) where n is the number of chained operations
- Notes: More memory intensive due to creating new objects, but provides immutability