Given a list of integers from 1 to 100, write functions to: (a) Return all even numbers, (b) Return all odd numbers, (c) Separate into two lists.
Answer
Overview
Filtering even and odd numbers is a fundamental list operation that demonstrates filtering, partitioning, and Dart's functional programming features. This common task appears in data processing, algorithm problems, and interview questions.
Even number: Divisible by 2 (
n % 2 == 0n % 2 != 0Approach 1: Using where() Method
Functional approach using Dart's built-in filtering.
dartList<int> getEvenNumbers(List<int> numbers) { return numbers.where((n) => n % 2 == 0).toList(); } List<int> getOddNumbers(List<int> numbers) { return numbers.where((n) => n % 2 != 0).toList(); } void main() { var numbers = List.generate(10, (i) => i + 1); // [1, 2, 3, ..., 10] print(getEvenNumbers(numbers)); // [2, 4, 6, 8, 10] print(getOddNumbers(numbers)); // [1, 3, 5, 7, 9] }
Time Complexity: O(n) Space Complexity: O(n) for result lists
Pros:
- Clean and readable
- Functional programming style
- One-liner solution
Approach 2: Loop-Based Filtering
Traditional imperative approach.
dartList<int> getEvenNumbersLoop(List<int> numbers) { List<int> evens = []; for (int n in numbers) { if (n % 2 == 0) { evens.add(n); } } return evens; } List<int> getOddNumbersLoop(List<int> numbers) { List<int> odds = []; for (int n in numbers) { if (n % 2 != 0) { odds.add(n); } } return odds; } void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; print(getEvenNumbersLoop(numbers)); // [2, 4, 6, 8, 10] print(getOddNumbersLoop(numbers)); // [1, 3, 5, 7, 9] }
Time Complexity: O(n) Space Complexity: O(n)
Approach 3: Partition into Two Lists
Separate into even and odd in a single pass.
dartMap<String, List<int>> partitionEvenOdd(List<int> numbers) { List<int> evens = []; List<int> odds = []; for (int n in numbers) { if (n % 2 == 0) { evens.add(n); } else { odds.add(n); } } return {'even': evens, 'odd': odds}; } void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var result = partitionEvenOdd(numbers); print(result['even']); // [2, 4, 6, 8, 10] print(result['odd']); // [1, 3, 5, 7, 9] }
Advantage: Single iteration for both lists.
Approach 4: Using Records (Dart 3.0+)
Modern Dart syntax with records for cleaner return type.
dart(List<int> evens, List<int> odds) partitionEvenOddRecord(List<int> numbers) { List<int> evens = []; List<int> odds = []; for (int n in numbers) { (n % 2 == 0 ? evens : odds).add(n); } return (evens, odds); } void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var (evens, odds) = partitionEvenOddRecord(numbers); print('Evens: $evens'); // Evens: [2, 4, 6, 8, 10] print('Odds: $odds'); // Odds: [1, 3, 5, 7, 9] }
Dart 3.0+ only - Uses record destructuring.
Approach 5: Custom Partition Function
Generic partition for any predicate.
dartclass Partition<T> { final List<T> matched; final List<T> unmatched; Partition(this.matched, this.unmatched); } Partition<T> partition<T>(List<T> items, bool Function(T) predicate) { List<T> matched = []; List<T> unmatched = []; for (T item in items) { (predicate(item) ? matched : unmatched).add(item); } return Partition(matched, unmatched); } void main() { var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Partition by even var result = partition(numbers, (n) => n % 2 == 0); print('Evens: ${result.matched}'); // [2, 4, 6, 8, 10] print('Odds: ${result.unmatched}'); // [1, 3, 5, 7, 9] // Works with any condition var byFive = partition(numbers, (n) => n >= 5); print('>=5: ${byFive.matched}'); // [5, 6, 7, 8, 9, 10] print('<5: ${byFive.unmatched}'); // [1, 2, 3, 4] }
Complete Solution Class
dartclass EvenOddFilter { // Get even numbers static List<int> getEvens(List<int> numbers) { return numbers.where((n) => n % 2 == 0).toList(); } // Get odd numbers static List<int> getOdds(List<int> numbers) { return numbers.where((n) => n % 2 != 0).toList(); } // Partition in single pass static Map<String, List<int>> partition(List<int> numbers) { List<int> evens = []; List<int> odds = []; for (int n in numbers) { (n % 2 == 0 ? evens : odds).add(n); } return {'even': evens, 'odd': odds}; } // Count evens and odds static Map<String, int> count(List<int> numbers) { int evens = 0, odds = 0; for (int n in numbers) { n % 2 == 0 ? evens++ : odds++; } return {'even': evens, 'odd': odds}; } // Check if all even static bool allEven(List<int> numbers) { return numbers.every((n) => n % 2 == 0); } // Check if all odd static bool allOdd(List<int> numbers) { return numbers.every((n) => n % 2 != 0); } // Check if any even static bool anyEven(List<int> numbers) { return numbers.any((n) => n % 2 == 0); } // Sum of evens and odds static Map<String, int> sum(List<int> numbers) { int evenSum = 0, oddSum = 0; for (int n in numbers) { n % 2 == 0 ? evenSum += n : oddSum += n; } return {'evenSum': evenSum, 'oddSum': oddSum}; } } void main() { var numbers = List.generate(10, (i) => i + 1); print(EvenOddFilter.getEvens(numbers)); // [2, 4, 6, 8, 10] print(EvenOddFilter.partition(numbers)); // {even: [2, 4, 6, 8, 10], odd: [1, 3, 5, 7, 9]} print(EvenOddFilter.count(numbers)); // {even: 5, odd: 5} print(EvenOddFilter.sum(numbers)); // {evenSum: 30, oddSum: 25} print(EvenOddFilter.allEven([2, 4, 6])); // true print(EvenOddFilter.anyEven([1, 3, 5, 6])); // true }
Comparison
| Approach | Time | Space | Readability | Best For |
|---|---|---|---|---|
text | O(n) | O(n) | ⭐⭐⭐⭐⭐ | Production |
| Loop-based | O(n) | O(n) | ⭐⭐⭐⭐ | Beginners |
| Partition (Map) | O(n) | O(n) | ⭐⭐⭐⭐ | Single pass |
| Partition (Record) | O(n) | O(n) | ⭐⭐⭐⭐⭐ | Dart 3.0+ |
| Generic | O(n) | O(n) | ⭐⭐⭐ | Reusability |
Generate Test Data
dartvoid generateTestData() { // 1 to 100 var range = List.generate(100, (i) => i + 1); print(getEvenNumbers(range).length); // 50 print(getOddNumbers(range).length); // 50 // Random numbers var random = List.generate(20, (_) => Random().nextInt(100)); print(partitionEvenOdd(random)); // Large dataset var large = List.generate(1000000, (i) => i); var sw = Stopwatch()..start(); partitionEvenOdd(large); print('Time: ${sw.elapsedMilliseconds}ms'); }
Edge Cases
dartvoid testEdgeCases() { // Empty list assert(getEvenNumbers([]).isEmpty); assert(getOddNumbers([]).isEmpty); // All even assert(getEvenNumbers([2, 4, 6]) == [2, 4, 6]); assert(getOddNumbers([2, 4, 6]).isEmpty); // All odd assert(getEvenNumbers([1, 3, 5]).isEmpty); assert(getOddNumbers([1, 3, 5]) == [1, 3, 5]); // Single element assert(getEvenNumbers([2]) == [2]); assert(getOddNumbers([3]) == [3]); // Zero (even by definition) assert(getEvenNumbers([0]) == [0]); // Negative numbers assert(getEvenNumbers([-2, -1, 0, 1, 2]) == [-2, 0, 2]); assert(getOddNumbers([-2, -1, 0, 1, 2]) == [-1, 1]); }
Best Practices
1. Use Functional Methods
dart// ✅ Clean and idiomatic List<int> evens(List<int> nums) => nums.where((n) => n.isEven).toList(); List<int> odds(List<int> nums) => nums.where((n) => n.isOdd).toList();
2. Use Built-in isEven/isOdd
dart// ✅ Dart provides these properties n.isEven // Better than n % 2 == 0 n.isOdd // Better than n % 2 != 0
3. Partition for Efficiency
dart// ✅ Single pass instead of two var (evens, odds) = partition(numbers); // ❌ Two passes var evens = numbers.where((n) => n.isEven).toList(); var odds = numbers.where((n) => n.isOdd).toList();
4. Handle Null Safety
dartList<int> getEvens(List<int>? numbers) { return numbers?.where((n) => n.isEven).toList() ?? []; }
Real-World Applications
1. Split Data for Processing
dartvar (evens, odds) = partition(data); processEvenData(evens); processOddData(odds);
2. Alternate Row Styling
dartWidget buildTable(List<Item> items) { return Column( children: items.asMap().entries.map((entry) { bool isEven = entry.key.isEven; return Container( color: isEven ? Colors.grey[100] : Colors.white, child: ItemRow(entry.value), ); }).toList(), ); }
3. Distribute Tasks
dartvoid distributeTasks(List<Task> tasks) { var (queue1, queue2) = partition( tasks.asMap().entries.toList(), (e) => e.key.isEven, ); worker1.process(queue1.map((e) => e.value).toList()); worker2.process(queue2.map((e) => e.value).toList()); }
Interview Tips
Common variations:
-
"Filter even indices vs. even values?"
- Clarify requirements
- text
list.asMap().entries.where((e) => e.key.isEven)
-
"In-place filtering?"
- for evens onlytext
list.removeWhere((n) => n.isOdd)
-
"Count instead of return?"
- text
numbers.where((n) => n.isEven).length
-
"Performance with huge lists?"
- Single-pass partition is best