rubyguides

Enumerable#drop_while

drop_while iterates through an enumerable, skipping elements from the start as long as the given condition evaluates to true. The moment the condition returns false for the first time, iteration stops and all remaining elements — including that first failing element — are returned as an array.

This makes drop_while ideal for situations where you want to ignore leading data that doesn’t meet a criterion, then process everything after that point.

Basic Usage

numbers = [1, 2, 3, 4, 5]

result = numbers.drop_while { |n| n < 3 }
result # => [3, 4, 5]

The method starts checking elements in order. It skips 1 and 2 because n < 3 is true for both. When it reaches 3, n < 3 is false, so it stops iterating and returns [3, 4, 5] — including 3 itself.

This behaviour means the first element that fails the test defines the boundary of the result. Everything before it is dropped; everything from it onward is kept, which makes the method especially useful for stripping headers, noise, or calibration data from the front of a sequence without knowing the exact count ahead of time.

drop_while vs drop

drop and drop_while serve different purposes:

  • drop(n) removes the first n elements regardless of their values.
  • drop_while removes elements only while the condition holds, stopping at the first false.
data = [nil, nil, 1, 2, nil, 3]

data.drop(2)         # => [1, 2, nil, 3]
data.drop_while { |x| x.nil? }  # => [1, 2, nil, 3]

Use drop when you know the exact count. Use drop_while when you need to skip elements based on a condition.

The two methods address different problems: drop is about a fixed offset, and drop_while is about a predicate. Choosing the right one depends on whether you know the position of the data you want to skip or whether you can describe it with a test. For dynamic data where the leading elements vary, drop_while is almost always the cleaner choice.

Stops at the first false

One key behavior: drop_while stops iterating entirely once the condition returns false for the first time. Elements after that point are returned regardless of whether they would have satisfied the condition.

mixed = [2, 4, 6, 7, 8, 9]

result = mixed.drop_while { |n| n.even? }
result # => [7, 8, 9]

Even though 8 is even and would satisfy n.even?, it is still included in the result because the iteration had already stopped at 7.

This is one of the most important things to understand about drop_while: it is not a filter. Once the condition fails, the method stops checking and returns everything that remains, regardless of whether later elements would have passed the test. That makes it a prefix-stripping operation, not a general-purpose removal tool.

Practical Examples

Skipping leading whitespace

lines = ["", "", "", "first line", "second line", ""]

content = lines.drop_while(&:empty?)
content # => ["first line", "second line", ""]

Useful for parsing configuration files, logs, or any text format where blank lines appear at the top. The &:empty? shorthand passes each line to the empty? method, so the block reads as “skip while the line is empty.” When the first non-blank line appears, iteration stops and all remaining content is returned, including any blank lines that appear further down in the file. This keeps the operation focused on the leading whitespace without disturbing the structure of the content that follows.

Skipping calibration data

readings = [0.0, 0.0, 0.0, 0.1, 0.2, 0.15, 0.3]

calibrated = readings.drop_while { |r| r == 0.0 }
calibrated # => [0.1, 0.2, 0.15, 0.3]

Drops initial zero readings from sensor data before the device stabilizes. Sensor data often starts with near-zero readings while the instrument warms up, and those values can skew averages or trigger false alarms. Using drop_while to discard them means the rest of the processing logic only sees readings from after the device has stabilised, without needing to know exactly how many samples to skip.

Skipping until a sentinel value

events = ["INFO", "INFO", "ERROR", "WARN", "INFO"]

critical = events.drop_while { |e| e != "ERROR" }
critical # => ["ERROR", "WARN", "INFO"]

Stops skipping when it encounters a sentinel value ("ERROR" in this case) and returns everything from that point on. This is a common pattern in log processing where you want to find and display everything from the first error onward. Unlike a filter that would remove non-error lines, drop_while preserves the full sequence after the sentinel, including any informational or warning messages that follow the first error.

Return Value

drop_while always returns an array:

[].drop_while { |x| true }  # => []
[1, 2, 3].drop_while { |x| false }  # => [1, 2, 3]

If the block never returns false, an empty array is returned. If the block returns false on the first element, all elements are returned.

See Also