Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterators and Enumerables #12

Merged
merged 26 commits into from
Jun 24, 2016
Merged

Iterators and Enumerables #12

merged 26 commits into from
Jun 24, 2016

Conversation

emirpasic
Copy link
Owner

@emirpasic emirpasic commented Jun 23, 2016

Closes #8

Iterator

Added stateful iterator to all ordered containers:

  • ArrayList
  • SinglyLinkedList
  • DoublyLinkedList
  • TreeMap
  • TreeSet
  • ArrayStack
  • LinkedListStack
  • BinaryHeap
  • RedBlackTree

Excluded unordered containers:

  • HashSet
  • HashMap

Two different types of iterators:

  • IteratorWithIndex (for containers whose elements are index by a numeric position)
  • IteratorWithKey (for containers whose elements are of type key value pairs)

Example:

// IteratorWithIndex
it := list.Iterator()
for it.Next() { // moves iterator to next, returns true if there was a next
    index := it.Index() // does not mutate iterator's state (type int)
    value := it.Value() // does not mutate iterator's state (type interface{})
    ...
}
// IteratorWithKey
it := map.Iterator()
for it.Next() { // moves iterator to next, returns true if there was a next
    key := it.Key() // does not mutate iterator's state (type interface{})
    value := it.Value() // does not mutate iterator's state (type interface{})
    ...
}

Enumerable

Added enumerable to:

  • ArrayList
  • SinglyLinkedList
  • DoublyLinkedList
  • TreeMap
  • TreeSet
  • ArrayStack

Two different types of enumerables:

  • EnumerableWithIndex (for containers whose elements are index by a numeric position)
  • EnumerableWithKey (for containers whose elements are of type key value pairs)

Enumerable is Ruby inspired and supports for now the following functions:

  • Each (iterate over elements of a container)
  • Map (creates new container by mapping each element into a new element)
  • Select (creates a new container by selecting only elements based on a criteria)
  • Any (returns true if any of the elements satisfy the criteria)
  • All (returns true if all of the elements satisfy the criteria)
  • Find (find the first element (index/key and value) in a container satisfying the criteria otherwise returns -1/nil, nil)

Example EnumerableWithIndex:

package main

import (
    "fmt"
    "github.com/emirpasic/gods/sets/treeset"
)

func printSet(txt string, set *treeset.Set) {
    fmt.Print(txt, "[ ")
    set.Each(func(index int, value interface{}) {
        fmt.Print(value, " ")
    })
    fmt.Println("]")
}

func main() {
    set := treeset.NewWithIntComparator()
    set.Add(2, 3, 4, 2, 5, 6, 7, 8)
    printSet("Initial", set) // [ 2 3 4 5 6 7 8 ]

    even := set.Select(func(index int, value interface{}) bool {
        return value.(int)%2 == 0
    })
    printSet("Even numbers", even) // [ 2 4 6 8 ]

    foundIndex, foundValue := set.Find(func(index int, value interface{}) bool {
        return value.(int)%2 == 0 && value.(int)%3 == 0
    })
    if foundIndex != -1 {
        fmt.Println("Number divisible by 2 and 3 found is", foundValue, "at index", foundIndex) // value: 6, index: 4
    }

    square := set.Map(func(index int, value interface{}) interface{} {
        return value.(int) * value.(int)
    })
    printSet("Numbers squared", square) // [ 4 9 16 25 36 49 64 ]

    bigger := set.Any(func(index int, value interface{}) bool {
        return value.(int) > 5
    })
    fmt.Println("Set contains a number bigger than 5 is ", bigger) // true

    positive := set.All(func(index int, value interface{}) bool {
        return value.(int) > 0
    })
    fmt.Println("All numbers are positive is", positive) // true

    evenNumbersSquared := set.Select(func(index int, value interface{}) bool {
        return value.(int)%2 == 0
    }).Map(func(index int, value interface{}) interface{} {
        return value.(int) * value.(int)
    })
    printSet("Chaining", evenNumbersSquared) // [ 4 16 36 64 ]
}

Example EnumerableWithKey:

package main

import (
    "fmt"
    "github.com/emirpasic/gods/maps/treemap"
)

func printMap(txt string, m *treemap.Map) {
    fmt.Print(txt, " { ")
    m.Each(func(key interface{}, value interface{}) {
        fmt.Print(key, ":", value, " ")
    })
    fmt.Println("}")
}

func main() {
    m := treemap.NewWithStringComparator()
    m.Put("g", 7)
    m.Put("f", 6)
    m.Put("e", 5)
    m.Put("d", 4)
    m.Put("c", 3)
    m.Put("b", 2)
    m.Put("a", 1)
    printMap("Initial", m) // { a:1 b:2 c:3 d:4 e:5 f:6 g:7 }

    even := m.Select(func(key interface{}, value interface{}) bool {
        return value.(int)%2 == 0
    })
    printMap("Elements with even values", even) // { b:2 d:4 f:6 }

    foundKey, foundValue := m.Find(func(key interface{}, value interface{}) bool {
        return value.(int)%2 == 0 && value.(int)%3 == 0
    })
    if foundKey != nil {
        fmt.Println("Element with value divisible by 2 and 3 found is", foundValue, "with key", foundKey) // value: 6, index: 4
    }

    square := m.Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
        return key.(string) + key.(string), value.(int) * value.(int)
    })
    printMap("Elements' values squared and letters duplicated", square) // { aa:1 bb:4 cc:9 dd:16 ee:25 ff:36 gg:49 }

    bigger := m.Any(func(key interface{}, value interface{}) bool {
        return value.(int) > 5
    })
    fmt.Println("Map contains element whose value is bigger than 5 is", bigger) // true

    positive := m.All(func(key interface{}, value interface{}) bool {
        return value.(int) > 0
    })
    fmt.Println("All map's elements have positive values is", positive) // true

    evenNumbersSquared := m.Select(func(key interface{}, value interface{}) bool {
        return value.(int)%2 == 0
    }).Map(func(key interface{}, value interface{}) (interface{}, interface{}) {
        return key, value.(int) * value.(int)
    })
    printMap("Chaining", evenNumbersSquared) // { b:4 d:16 f:36 }
}
  • Tests (100% Complete)
  • Documentation (100% Complete)
  • Examples (100% Complete)

- create examples for enumerables operations
…this requires type assertions in chaining, which is really ugly and unnecessary. the only drawback is that one might forget to implement those functions and interface implementations asserts will not register that. (need help on this)
@emirpasic emirpasic merged commit 714650c into master Jun 24, 2016
@emirpasic emirpasic deleted the enums branch June 24, 2016 05:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant