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

#!ek9
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: cheapest, find, head, minimum, smallest, sort, stream