Part of Github Copilot with Kotlin

Kotlin with Coilot: Create a list of 10 numbers and use lambda function to find the even numbers

Sandy LaneSandy Lane

Video: Kotlin with Coilot: Create a list of 10 numbers and use lambda function to find the even numbers by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

Kotlin: List 1-10 and Filter to Find Even Numbers

(1..10).toList() for the range as a list. filter { it % 2 == 0 } for evens. Two stdlib operations, three lines.

A small puzzle that combines range construction with the filter idiom from episode 24.

The Copilot prompt

fun main() {
  // Create a list of 10 numbers and filter for even ones

Copilot generates:

val numbers = (1..10).toList()
val evenNumbers = numbers.filter { it % 2 == 0 }
println("Even numbers: $evenNumbers")   // [2, 4, 6, 8, 10]

Walkthrough

1. (1..10) — a IntRange. Inclusive on both ends — 1 through 10. IntRange is a class, supports iteration, contains, step, etc.

2. .toList() — convert to List<Int>. IntRange is iterable but not a List. toList() materializes the range into a list (a 10-element copy).

For just iterating, you don't need the list:

for (n in 1..10) println(n)
(1..10).forEach { println(it) }

But for storing, passing around, or doing further list operations, .toList() is convenient.

3. .filter { it % 2 == 0 }. The same idiom from episode 24. Returns [2, 4, 6, 8, 10].

Skipping .toList() when chaining

If you're going straight into more operations, the conversion is wasted:

// Wasteful:
val evens = (1..10).toList().filter { it % 2 == 0 }

// Better:
val evens = (1..10).filter { it % 2 == 0 }

IntRange has filter, map, etc. directly — they return List<Int> already. No need to materialize first.

For huge ranges, even better — asSequence():

val evens = (1..1_000_000).asSequence()
  .filter { it % 2 == 0 }
  .take(10)
  .toList()

take(10) short-circuits — only the first 10 evens are computed. Without asSequence(), we'd filter all 1M before taking 10.

Range variations

val a = 1..10               // 1, 2, ..., 10
val b = 1 until 10          // 1, 2, ..., 9 (exclusive)
val c = 10 downTo 1         // 10, 9, ..., 1
val d = 1..10 step 2        // 1, 3, 5, 7, 9
val e = (1..10).reversed()  // 10, 9, ..., 1

.. is inclusive, until is exclusive (matches for i in range(10) from Python). downTo for descending. step to skip.

More compact: just the evens

val evens = (2..10 step 2).toList()   // [2, 4, 6, 8, 10]

Step by 2 starting at 2 — every even up to 10. No filter needed. Faster too — generates 5 elements instead of 10.

For a generic "every Nth," use step. For "every element matching a predicate," use filter. They overlap in simple cases like this.

Different range types

  • 1..10IntRange
  • 1L..10LLongRange
  • 'a'..'z'CharRange ("abc...xyz")
  • 1.0..10.0 → ❌ doesn't compile; floats need explicit step

For floats, use:

val floats = generateSequence(0.0) { it + 0.1 }
  .takeWhile { it <= 1.0 }
  .toList()

Or convert from integer ticks:

val floats = (0..10).map { it / 10.0 }

The result is List<Int>

(1..10).filter { ... } returns List<Int>, not IntRange. The output is a regular list with all the standard list methods.

Common mistakes

1..10 excluding 10. It's inclusive. 1 until 10 is exclusive. Different from many languages.

(1..10) thinking it's a List. It's an IntRange. Iterates fine, but doesn't have [i] random access (well, it does — (1..10).elementAt(0) works, but it's O(n) for ranges with step).

Materializing huge ranges. (1..Int.MAX_VALUE).toList() allocates ~8 GB. Use sequences for huge ranges.

Confusing step and skip. step says "increment by N." There's no skip for ranges (you'd use drop(n) to start later).

Negative step without downTo. 1..10 step -1 errors. Use 10 downTo 1 for descending.

What's next

Episode 29: One-line lambda function. Compress the lambda syntax further when the body is a single expression.

Recap

(1..10) is an IntRange, inclusive. .toList() materializes; or use .filter {...} directly (returns List). For "every Nth," step N. For descending, downTo. For exclusive upper bound, until. For huge or expensive sequences, asSequence().filter().take(n).toList() to short-circuit. (2..10 step 2) is the explicit "evens 2-10" range — sometimes clearer than filter.

Next episode: one-line lambdas.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.