Skip to content

Instantly share code, notes, and snippets.

@nilesh-akhade
Last active September 22, 2022 06:35
Show Gist options
  • Save nilesh-akhade/5b094139c143ed21ae6ce88e1dd35500 to your computer and use it in GitHub Desktop.
Save nilesh-akhade/5b094139c143ed21ae6ce88e1dd35500 to your computer and use it in GitHub Desktop.
Implement an iterator to retrieve Baskets and Bouquets from Plucker. The Plucker is an iterator which returns either Flower or Fruit from `orchard.json`
package main
import "fmt"
type Iterator interface {
Next() interface{}
HasNext() bool
}
type Flower struct {
Name string
Colour string
Smell string
}
type Fruit struct {
Name string
Colour string
Taste string
}
func NewPlucker(filename string) Iterator {
return nil // assume implemented
}
type Bouquet []Flower
type Basket []Fruit
type bouquetBasketIterator struct {
plucker Iterator
bouquetSize int
basketSize int
current interface{} // Basket or Bouquet
lastItem interface{} // Flower or Fruit
hasNoMore bool // if true, underlying iterator(plucker) has no more elems
}
func NewBouqBasketIterator(plucker Iterator, bouquetSize int, basketSize int) Iterator {
return &bouquetBasketIterator{
plucker: plucker,
bouquetSize: bouquetSize,
basketSize: basketSize,
}
}
func (b *bouquetBasketIterator) Next() interface{} {
if b.hasNoMore {
return nil
}
if b.current == nil {
firstItem := b.next()
if firstItem == nil {
return nil
}
b.current = b.next() // buffer next item
return firstItem
}
current := b.current
b.current = b.next()
return current
}
func (b *bouquetBasketIterator) next() interface{} {
basket := make(Basket, b.basketSize)
bouquet := make(Bouquet, b.bouquetSize)
if b.lastItem != nil {
switch b.lastItem.(type) {
case Flower:
flower := b.lastItem.(Flower)
bouquet = append(bouquet, flower)
if len(bouquet) == b.basketSize { // if size==1
return bouquet
}
case Fruit:
fruit := b.lastItem.(Fruit)
basket = append(basket, fruit)
if len(basket) == b.basketSize {
return basket
}
}
}
for b.plucker.HasNext() {
i := b.plucker.Next()
switch v := i.(type) {
case Flower:
flower := i.(Flower)
bouquet = append(bouquet, flower)
if len(bouquet) == b.bouquetSize { // if full return
return bouquet
}
if len(basket) != 0 { // flower consumed while basket was not completely full
b.lastItem = flower
return basket
}
case Fruit:
fruit := i.(Fruit)
basket = append(basket, fruit)
if len(basket) == b.basketSize {
return basket
}
if len(bouquet) != 0 {
b.lastItem = fruit
return bouquet
}
default:
fmt.Printf("Unknown type ignored %T!\n", v)
}
}
b.hasNoMore = true
return nil
}
func (b *bouquetBasketIterator) HasNext() bool {
if b.hasNoMore {
return false
}
if b.current == nil {
firstItem := b.next()
if firstItem == nil {
return false
}
b.current = b.next()
}
return true
}
func main() {
iterator := NewBouqBasketIterator(NewPlucker("orchard.json"), 10, 12)
for iterator.HasNext() {
i := iterator.Next()
switch v := i.(type) {
case Bouquet:
bouquet := i.(Bouquet)
fmt.Printf("Bouquet is %v\n", bouquet)
case Basket:
basket := i.(Basket)
fmt.Printf("Basket is %v\n", basket)
default:
fmt.Printf("Unknown type %T!\n", v)
}
}
}
{
"location": "Amsterdam",
"fruits":[{"name":"apple","color":"red"},{"name":"banana","color":"yellow"}],
"flowers":[{"name":"tulip", "color":"white"}]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment