The `each_cons`

method in Ruby on Rails is a versatile tool that simplifies iterating over consecutive pairs in a collection. With just a single line of code, we can perform tasks such as finding patterns or calculating differences between adjacent elements. In this blog post, we’ll explore the various use cases of `each_cons`

, starting from simple examples and gradually progressing to more complex ones.

**Simple Example**: let’s start with a basic example using an array of numbers. Here, `each_cons(2)`

iterates over consecutive pairs within the `numbers`

array. The variable `pair`

receives an array containing two adjacent elements on each iteration.

1
2
3
4
5
6
7
8
9
10
11

numbers = [1, 2, 3, 4, 5]
numbers.each_cons(2) do |pair|
puts "Pair: #{pair}"
# Additional logic to manipulate the pair
end
#=> Pair: [1, 2]
#=> Pair: [2, 3]
#=> Pair: [3, 4]
#=> Pair: [4, 5]

**Finding Patterns**: `each_cons`

is handy for identifying patterns in a sequence. Here, `each_cons(3)`

iterates over consecutive triples of characters in the `text`

string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

text = "Hello, world!"
text.chars.each_cons(3) do |triple|
puts "Triple: #{triple.join}"
# Additional logic to analyze the triple
end
#=> Triple: Hel
#=> Triple: ell
#=> Triple: llo
#=> Triple: lo,
#=> Triple: o,
#=> Triple: , w
#=> Triple: wo
#=> Triple: wor
#=> Triple: orl
#=> Triple: rld
#=> Triple: ld!

In this example, we use `each_cons(2)`

to iterate over consecutive pairs of words in the words array. The `max_by`

method is used to find the pair with the maximum difference in length. In this case, the longest consecutive sequence is between `elephant`

and `frog`

.

1
2
3
4
5
6
7

words = ["apple", "banana", "cat", "dog", "elephant", "frog", "giraffe"]
longest_sequence = words.each_cons(2).max_by { |w1, w2| w2.length - w1.length }
puts "Longest consecutive sequence: #{longest_sequence}"
#=> Longest consecutive sequence: ["elephant", "frog"]

**Calculating Prices Differences**: `each_cons`

is also useful for calculating differences between adjacent elements. In this example, `each_cons(2)`

is combined with `map`

to calculate the differences between consecutive elements in the `prices`

array.

1
2
3
4
5
6
7

prices = [10.5, 12.3, 11.8, 14.2, 13.5]
differences = prices.each_cons(2).map { |pair| pair[1] - pair[0] }
puts "Price differences: #{differences}"
# => Price differences: [1.8, -0.5, 2.4, -0.7]

**Adding Numbers**: In this example, we use `each_cons(2)`

to iterate over consecutive pairs of numbers in the `numbers`

array. The `map`

method calculates the sum of each pair, resulting in the array `[4, 8, 12, 16]`

.

1
2
3
4
5
6
7

numbers = [1, 3, 5, 7, 9]
sums = numbers.each_cons(2).map { |n1, n2| n1 + n2 }
puts "Pair sums: #{sums}"
# => Pair sums: [4, 8, 12, 16]

**Advanced Analysis**: `each_cons`

can handle more complex scenarios, such as analyzing sequences of objects. Considering an array of hashes, `each_cons(3)`

iterates over consecutive triples of hashes in the `data`

array. We calculate the average value of each triple based on the `value`

attribute and print it to the console.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

data = [
{ id: 1, value: 10 },
{ id: 2, value: 15 },
{ id: 3, value: 12 },
{ id: 4, value: 20 }
]
data.each_cons(3) do |triple|
average = triple.sum { |hash| hash[:value] } / triple.size.to_f
puts "Triple average: #{average}"
end
# => Triple average: 12.333333333333334
# => Triple average: 15.666666666666666
# => Triple average: 15.666666666666666

**Stock Market Analysis**: suppose you have an array of stock prices representing the closing prices of a stock over several days. You can use `each_cons`

to calculate the percentage change between consecutive closing prices, allowing you to analyze the volatility of the stock.

1
2
3
4
5
6
7

prices = [100.5, 102.3, 98.7, 105.2, 99.8, 101.4, 98.2]
percentage_changes = prices.each_cons(2).map { |p1, p2| ((p2 - p1) / p1) * 100 }
puts "Percentage changes: #{percentage_changes}"
# => Percentage changes: [1.791044776119407, -3.5114503816793835, 6.595744680851055, -5.13245033112583, 1.603206412825632, -3.1653439153439157]

**Fitness Tracker**: imagine you have an array of daily step counts representing a person’s activity levels. You can use `each_cons`

to identify streaks of consecutive days where the person achieved a certain step count goal, helping track their consistency.

1
2
3
4
5
6
7

step_counts = [5000, 6000, 7500, 8000, 4000, 9000, 9500, 10000, 11000]
goal_streaks = step_counts.each_cons(3).select { |counts| counts.all? { |count| count >= 8000 } }
puts "Goal streaks: #{goal_streaks}"
# => Goal streaks: [[8000, 9000, 9500], [9000, 9500, 10000], [9500, 10000, 11000]]

**Time Series Analysis:** suppose you have an array of temperature measurements taken at regular intervals throughout the day. You can use `each_cons`

to identify patterns or anomalies by comparing consecutive temperature values.

1
2
3
4
5
6
7

temperatures = [25.2, 25.5, 25.8, 26.1, 25.9, 26.3, 26.0, 25.7]
anomalies = temperatures.each_cons(4).select { |temps| temps.max - temps.min > 0.5 }
puts "Temperature anomalies: #{anomalies}"
# => Temperature anomalies: [[25.2, 25.5, 25.8, 26.1], [25.9, 26.3, 26.0, 25.7]]