What improvements/ optimizations can be made to the code?

This blog equips you with essential techniques to streamline your code for blazing-fast performance. We'll cover data structures, loops, caching, and more, helping you write efficient code.
What improvements/ optimizations can be made to the code?

This blog post delves into the world of code optimization, offering practical strategies to enhance the performance of your code. We'll explore how to choose the right data structures for the task, minimize unnecessary loops and calculations, leverage caching techniques effectively, and write clean, DRY (Don't Repeat Yourself) code. We'll also delve into the importance of considering time and space complexity when crafting your code.

Use efficient data structures

Choose the right data structure for your task.

Example: Arrays are fast for indexing, while hashes are better for key-value lookups.

# Inefficient
names = ["Alice", "Bob", "Charlie"]
names.include?("Bob") # Searches through entire array

# Optimized
names_set = Set.new(["Alice", "Bob", "Charlie"])
names_set.include?("Bob") # Faster lookup

Minimize loops and iterations

Reduce the number of times you loop through data.

# Inefficient: Multiple loops through the same data
numbers = [1, 2, 3, 4, 5]
sum = 0
product = 1
max = numbers[0]
min = numbers[0]

numbers.each { |n| sum += n }
numbers.each { |n| product *= n }
numbers.each { |n| max = n if n > max }
numbers.each { |n| min = n if n < min }

# Optimized: Single loop to calculate all values
numbers = [1, 2, 3, 4, 5]
sum = 0
product = 1
max = numbers[0]
min = numbers[0]

numbers.each do |n|
  sum += n
  product *= n
  max = n if n > max
  min = n if n < min
end

Avoid unnecessary calculations

Don't repeat calculations that don't change.

Example: storing the result of a calculation that doesn't change, and then reusing that stored result instead of recalculating it.

class ExpensiveCalculation
  def initialize
    @result = nil
  end

  def calculate
    @result ||= perform_expensive_calculation
  end

  private

  def perform_expensive_calculation
    puts "Performing expensive calculation..."
    # Simulating an expensive calculation
    sleep(2)
    42
  end
end

calculation = ExpensiveCalculation.new

# First call, performs the calculation
puts calculation.calculate # => Performing expensive calculation... 42

# Second call, uses the cached result
puts calculation.calculate # => 42

Employ caching techniques

Store results of expensive operations for reuse.

The Fibonacci sequence, when implemented recursively, often leads to redundant calculations. For instance, the standard recursive approach calculates the same Fibonacci numbers multiple times. We can avoid this inefficiency by using alternative methods like an iterative approach or tail recursion. These techniques allow us to store intermediate results in variables, eliminating the need for repeated calculations. This principle of storing results instead of recalculating them can be applied to many other scenarios to improve code efficiency. For more information, visit https://vulehuan.com/en/blog/2024/7/unraveling-recursion-understanding-the-magic-behind-it-66951167cdb8828661f4c415.html

Web caching ideas:

Optimize conditional statements

Order conditions efficiently and use case when appropriate.

# Inefficient
if x == 1
  puts "One"
elsif x == 2
  puts "Two"
elsif x == 3
  puts "Three"
end

# Optimized
case x
when 1 then puts "One"
when 2 then puts "Two"
when 3 then puts "Three"
end

Use built-in functions and libraries

Example: Ruby has many efficient built-in methods. Use them!


# Inefficient
words = text.split(" ")
word_count = {}
words.each do |word|
  word_count[word] ||= 0
  word_count[word] += 1
end

# Optimized
word_count = text.split.tally

Remove redundant code

Don't repeat yourself. Consolidate repeated code into functions.

Have you heard of DRY (Don't Repeat Yourself)?? It avoids code duplication, promoting cleaner and more maintainable code. For more information, visit https://vulehuan.com/en/blog/2024/7/write-cleaner-maintainable-code-with-dry-kiss-solid-principles-6688ca8bc9dec2dec37a1b94.html

Consider time and space complexity

Think about how your code scales with larger inputs.

# O(n^2) time complexity
def has_duplicate?(array)
  array.each_with_index do |item, i|
    array[(i+1)..-1].each do |other|
      return true if item == other
    end
  end
  false
end

# O(n) time complexity, O(n) space complexity
def has_duplicate?(array)
  seen = Set.new
  array.each do |item|
    return true if seen.include?(item)
    seen.add(item)
  end
  false
end