Start learning free

LESSON 276 OF 677 · PAIRS, SORTING & BUILT-INS

Price List in Kotlin with zip and withIndex

Practice Read the full explanation

You get an ArrayList of strings items and an ArrayList of integers prices. Return an ArrayList of strings with one line per item.

The price at each index belongs to the item at the same index.

A line looks like "1. apple: 3". It has the item's number, then the item, then its price.

The numbers start at 1. The lines keep the order of items.

 

Example 1:

Input: items = ["apple", "bread", "milk"], prices = [3, 2, 4]
Output: ["1. apple: 3", "2. bread: 2", "3. milk: 4"]
Explanation: The apple is first and costs 3.
The bread is second and costs 2.
The milk is third and costs 4.

Example 2:

Input: items = ["tea"], prices = [5]
Output: ["1. tea: 5"]
Explanation: One item gives one line, number 1.

Example 3:

Input: items = ["pen", "pen", "ink"], prices = [2, 3, 0]
Output: ["1. pen: 2", "2. pen: 3", "3. ink: 0"]
Explanation: The shop sells two kinds of pen.
Each one gets its own line, number and price.
The ink is free, so its price is 0.

 

Constraints:

  • items and prices have the same length.
  • They have 1 to 100 entries.
  • Each item is one word of lowercase letters.
  • Each price is a whole number from 0 to 1000.
STEP 1 OF 5
    Ctrl + Enter to check

    KOTLIN · PAIRS, SORTING & BUILT-INS

    Price List in Kotlin, explained

    Problem overview

    priceList receives a list of strings items and a list of integers prices of the same length. The price at each index belongs to the item at the same index. It returns one line per item, like "1. apple: 3": the item's number (starting at 1), a dot and a space, the item, a colon and a space, then the price. The lines keep the order of items.

    For ["apple", "bread", "milk"] and [3, 2, 4] the lines are 1. apple: 3, 2. bread: 2 and 3. milk: 4. For ["pen", "pen", "ink"] and [2, 3, 0] each pen gets its own line, because the lines are matched by position: 1. pen: 2, 2. pen: 3, 3. ink: 0.

    Approach

    Two things are needed for each line: the item with its price, and the item's number. items.zip(prices) gives the first, a list of pairs (item, price). withIndex() adds the second, the position from 0. Chained, items.zip(prices).withIndex() gives an index and a pair on each pass. The index starts at 0, so the line number is i + 1.

    Step by step

    1. Make an empty mutableListOf<String>() named lines.
    2. Loop with for ((i, pair) in items.zip(prices).withIndex()). The loop variable pair is the pair of item and price.
    3. Unpack it inside the loop: val (item, price) = pair. A for line can't unpack a pair inside a pair, so this step is a separate line.
    4. Add the line to lines with a string template: "${i + 1}. $item: $price".
    5. After the loop, return lines.

    The solution in Kotlin

    class Solution {
        fun priceList(items: List<String>, prices: List<Int>): List<String> {
            val lines = mutableListOf<String>()
            for ((i, pair) in items.zip(prices).withIndex()) {
                val (item, price) = pair
                lines.add("${i + 1}. $item: $price")
            }
            return lines
        }
    }
    

    On the three examples it returns:

    [1. apple: 3, 2. bread: 2, 3. milk: 4]
    [1. tea: 5]
    [1. pen: 2, 2. pen: 3, 3. ink: 0]
    

    (Kotlin prints a list with brackets and commas; each element is one line of the result.)

    What each piece holds

    For the first example, items.zip(prices) is [(apple, 3), (bread, 2), (milk, 4)]. Adding withIndex() numbers those pairs from 0, so the loop sees index 0 with the pair for apple, index 1 with the pair for bread, and index 2 with the pair for milk. On each pass, item and price come from unpacking that pass's pair, and the line is built from the three values. A single item, as in the second example, makes the loop run once and produce 1. tea: 5.

    Details worth knowing

    The string template needs ${i + 1} in braces because it is an expression. A plain $item works for a single variable name. Writing $i + 1 inside the string would insert the index and then the plain text + 1, giving 0 + 1. apple: 3 for the first line.

    Because the lengths are equal, zip loses nothing. If they weren't, zip would stop at the shorter list without an error.

    Another way

    The loop and the lines list can be replaced by mapIndexed, which calls a lambda with the index and each pair, and collects the results. The lambda can unpack the pair in its own parameters:

    val lines = items.zip(prices).mapIndexed { i, (item, price) -> "${i + 1}. $item: $price" }
    

    It gives the same result, [1. apple: 3, 2. bread: 2, 3. milk: 4], for the first example. The loop version is the one the lesson builds, and it keeps every step visible.

    Edge cases and common mistakes

    • Numbering from 0. Printing $i gives 0. apple: 3. Use ${i + 1}.
    • Nested unpacking in the for line. for ((i, (item, price)) in ...) doesn't compile; unpack the pair in the body.
    • Looking prices up by item. With repeated items such as the two pens, a lookup by name would find the wrong price. Matching by position is what keeps both lines right.
    • Wrong separators. The tests compare the lines exactly: a dot and a space after the number, a colon and a space before the price.
    Keep going with Kotlin500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free