Find the cheapest product in a list.

← Operators and Expressions · Ref: Q1086

Sort by the price, then take the first:

  cheapest <- cat products | sort by byPrice | head 1 | collect as List of Product

where byPrice is a pure comparator function:

  byPrice() as pure
    ->
      left as Product
      right as Product
    <- rtn as Integer: left.price <=> right.price

For the maximum, sort by a descending comparator (right.price <=> left.price) and take head 1. A plain 'sort' uses the record's own <=> from 'default operator', which compares the fields in declaration order (name first) - it only finds the cheapest if price is the first field, so name the key with 'sort by'.

See Q1085 for sorting records. See Q1073 for descending sort.

Example

defines module qa.operators.findcheapestproduct

  defines record

    Product
      name as String: String()
      price as Float: Float()

      Product()
        ->
          name as String
          price as Float
        this.name :=: name
        this.price :=: price

      default operator

  defines function

    byPrice() as pure
      ->
        left as Product
        right as Product
      <- rtn as Integer: left.price <=> right.price

    byPriceDescending() as pure
      ->
        left as Product
        right as Product
      <- rtn as Integer: right.price <=> left.price

  defines program

    FindCheapestProductDemo()
      stdout <- Stdout()

      products <- List() of Product
      products += Product("Keyboard", 49.99)
      products += Product("Mouse", 19.99)
      products += Product("Monitor", 299.99)
      products += Product("Cable", 9.99)

      //Find cheapest: sort by price ascending, take first
      cheapest <- cat products | sort by byPrice | head 1 | collect as List of Product
      stdout.println(`Cheapest: ${cheapest}`)

      //Find most expensive: sort by price descending, take first
      priciest <- cat products | sort by byPriceDescending | head 1 | collect as List of Product
      stdout.println(`Priciest: ${priciest}`)

      //A plain 'sort' uses the record's own <=> from 'default operator',
      //which compares the fields in declaration order - name first
      firstByName <- cat products | sort | head 1 | collect as List of Product
      stdout.println(`First by name: ${firstByName}`)

Common mistakes

E50060 — EK9 has no .min() method. Use a stream pipeline: sort by a price comparator, then head 1 to get the cheapest.

Incorrect:

      cheapest <- products.min()

Correct:

      cheapest <- cat products | sort by byPrice | head 1 | collect as List of Product
Other ways to ask this
  • Get the minimum item from a collection using a stream
  • Extract the smallest record from a sorted list
  • In Python I'd use min(). How do I find the minimum in EK9?
  • I have a list of products and need the one with the lowest price

Coming from another language?

Java: Collections.min(list, Comparator.comparing(Product::price)). Python: min(products, key=lambda p: p.price). Rust: iter().min_by_key(). EK9: cat list | sort by byPrice | head 1 | collect.

Keywords: smallest, find, stream, cheapest, head, minimum, sort