I need to find the cheapest item in each category. How would I approach this in EK9?

← Streams and Pipelines · Ref: Q990

APPROACH:

1. Sort products by category (required before grouping)
2. Group by category — produces a stream of Lists, one per category
3. Map each group to find its minimum-priced item
4. Collect the results or output directly

STREAM PIPELINE:

  cat products
    | sort by compareCategory
    | group by extractCategory
    | map with findCheapestInGroup
    | collect as List of Product

FUNCTIONS NEEDED:

- compareCategory: compares two Products by their category field
- extractCategory: extracts the category String from a Product
- findCheapestInGroup: takes a List of Product, returns the one with lowest price

The findCheapestInGroup function itself can use a stream:

  cat group | sort by comparePrice | head 1 | collect as List of Product

This decomposes a complex task into small, testable, pure functions connected by a pipeline.

Example

defines module qa.streams.planapproach

  defines record

    Product
      productName as String: String()
      category as String: String()
      price as Float: 0.0

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

      default operator

  defines function

    compareCategory() as pure
      ->
        left as Product
        right as Product
      <- rtn as Integer: left.category <=> right.category

    extractCategory() as pure
      -> product as Product
      <- rtn as String: product.category

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

  defines program

    PlanApproachDemo()
      stdout <- Stdout()

      products <- [
        Product("Widget", "Tools", 29.99),
        Product("Gadget", "Electronics", 149.99),
        Product("Wrench", "Tools", 15.50),
        Product("Phone", "Electronics", 899.00),
        Product("Hammer", "Tools", 22.00),
        Product("Tablet", "Electronics", 349.00)
      ]

      //Sort by category, group, then output grouped
      stdout.println("Products by category:")
      cat products
        | sort by compareCategory
        | group by extractCategory
        > stdout

Common mistakes

E10040 — Must sort before group in EK9. The grouping algorithm requires sorted input. See ek9 -h E10040.

Incorrect:

      cat products
        | group by extractCategory

Correct:

      cat products
        | sort by compareCategory
        | group by extractCategory
Other ways to ask this
  • What EK9 constructs would I use to find minimums per group?
  • How do I decompose a group-and-find-minimum task in EK9?
  • Plan an approach for finding the best value per category

Coming from another language?

EK9 decomposes group-and-reduce tasks into sort, group, map steps connected by a pipeline. Each step is a named pure function.

Keywords: decompose, approach, plan, stream, group, minimum