Iterator
.pred
.
functional :: iter_extras $ Array
Resizable one dimension array of objects.functional :: iter_extras $ Iterator
Iterators generate a series of elements, one at a time.functional :: iter_extras $ Array
Resizable one dimension array of objects.pred
.
functional :: iter_extras $ Iterator
Iterators generate a series of elements, one at a time.core :: union_find
union–find algorithm using an efficient disjoint-set data structurefunctional :: functional_types
This module provides functional type to represents various function forms.
# This modules provides a new functional interface for `Iterator`.
module iter_extras
import functional_types
import cartesian
redef class Array
# Sorts an array with a function.
#
# ~~~~nitish
# class Person
# var name: String
# end
#
# def get_name(p: Person) do return p.name
#
# var ps = [new Person("Turing"), new Person("Curry"), new Person("Alfredo")]
# ps.sort_with(&get_name)
# assert ps[0].name == "Alfredo"
# assert ps[1].name == "Curry"
# assert ps[2].name == "Turing"
# ~~~~
fun sort_with(f: Fun1[E, Comparable])
do
var cmp = new ComparatorWith[E](f)
if length > 1 then
cmp.quick_sort(self, 0, length - 1)
end
end
end
redef interface Iterator[E]
# Applies a function to every elements
#
# ~~~~nitish
# fun add(x: Int): Int do return x + 1
#
# var f = &add
# var xs = [1,2,3,4,5]
# var actual = xs.iterator.map(f).to_a
# assert actual == [2,3,4,5,6]
# ~~~~
fun map(f: Fun1[E,Object]): MapIter[E,Object]
do
return new MapIter[E,Object](self, f)
end
# Iterator that gives the current count and element as a pair
fun enumerate: EnumerateIter[E]
do
return new EnumerateIter[E](self)
end
# Iterator that filters elements by a predicate
#
# ~~~~nitish
# fun lt10(x: Int): Bool do return x < 10
#
# var pred = <10
# var xs = [1..20]
# var actual = xs.iterator.filter(pred).to_a
# assert actual == [1..9].to_a
# ~~~~
fun filter(pred: Fun1[E,Bool]): FilterIter[E]
do
return new FilterIter[E](self,pred)
end
# Checks if at least one element respects a predicate
#
# ~~~~nitish
# fun eq10(x: Int): Bool do return x == 10
#
# var pred = &eq10
# var xs = [1,2,5,7,9,10,44]
# assert xs.iterator.any(pred)
# var ys = []
# assert not ys.iterator.any(pred)
# assert not [1,2,44].iterator.any(pred)
# ~~~~
fun any(pred: Fun1[E,Bool]): Bool
do
for x in self do
if pred.call(x) then
return true
end
end
return false
end
# Checks if all elements respect a predicate
#
# ~~~~nitish
# fun lt10(x: Int): Bool do return x < 10
#
# var pred = <10
# var xs = [1..9]
# assert xs.iterator.all(pred)
# assert [].iterator.all(pred)
# assert not [1..10].iterator.all(pred)
# ~~~~
fun all(pred: Fun1[E,Bool]): Bool
do
for x in self do
if not pred.call(x) then
return false
end
end
return true
end
# Folds an iterator from the left
#
# ~~~~nitish
# fun adder(x: Int, y: Int): Int do return x + y
#
# var xs = [1..10]
# assert xs.iterator.fold(0, &adder) == 55
# ~~~~
fun fold(acc: Object, f: Fun2[Object, E, Object]): Object
do
for x in self do
acc = f.call(acc, x)
end
return acc
end
# Folds and apply two element at a time
#
# ~~~~nitish
# fun min_int(x: Int, y: Int): Int
# do
# if x < y then return x
# return y
# end
#
# var xs = [100,423,51,1,-19,55,999,-18]
# assert xs.iterator.fold1(&min_int) == -19
# ~~~~
# REQUIRE : length > 1
fun fold1(f: Fun2[E,E,E]): E
do
var a1 = item
next
var a2 = item
next
var res = f.call(a1,a2)
for x in self do
res = f.call(res, x)
end
return res
end
# Apply a mutation function over all elements
#
# ~~~~nitish
# class Person
# var age: Int
# def incr_age
# do
# age += 1
# end
# end
#
# var ps = [new Persone(1), new Person(2), new Person(3)]
# var ages = ps.iterator.for_each(&Person::incr_age).map(&Person::age).to_a
# assert ages == [2,3,4]
# ~~~~
fun for_each(f: Proc1[E])
do
for x in self do
f.call(x)
end
end
# Maps every element to a nested structure then flattens it
#
# ~~~~nitish
# fun chars_fn(s: String): Iterator[Char]
# do
# return s.chars.iterator
# end
# var cs = ["aaa","bbb","ccc"]
# assert cs.iterator.flat_map(&chars_fn).to_a.join == "aaabbbccc"
# ~~~~
fun flat_map(f: Fun1[E, Iterator[Object]]): FlatMapIter[E, Object]
do
return new FlatMapIter[E, Object](self, f)
end
# Generates an `Iterator` whose elements are sorted by the function
# passed in argument.
#
# ~~~~nitish
# class Person
# var name: String
# end
#
# def get_name(p: Person) do return p.name
#
# var ps = [new Person("Turing"), new Person("Curry"), new Person("Alfredo")]
# var ordered_names = ps.iterator.order_by(&get_name).map(&get_name).to_a
# assert ordered_names == ["Alfredo", "Curry", "Turing"]
# ~~~~
fun order_by(f: Fun1[E, Comparable]): OrderedIter[E]
do
return new OrderedIter[E](self, f)
end
end
# Base class for all iterators using functional types.
private abstract class FunIter[OLD,NEW]
super Iterator[NEW]
var my_iter: Iterator[OLD]
redef fun next
do
my_iter.next
end
redef fun start
do
my_iter.start
end
redef fun finish
do
my_iter.finish
end
redef fun is_ok
do
return my_iter.is_ok
end
end
# An iterator that maps each item with `f`.
class MapIter[A,B]
super FunIter[A,B]
var f: Fun1[A, B]
redef fun item
do
return f.call(my_iter.item)
end
end
# An iterator that maps each item to a pair containing the item with its
# current count.
class EnumerateIter[E]
super FunIter[E, Pair[Int,E]]
redef fun item
do
return new Pair[Int,E](0, my_iter.item)
end
end
# An tierator that filter its element by a predicate `pred`.
class FilterIter[E]
super FunIter[E,nullable E]
var pred: Fun1[E, Bool]
redef init
do
if is_ok and not pred.call(my_iter.item) then next
end
redef fun item
do
assert is_ok
return my_iter.item
end
redef fun next
do
loop
my_iter.next
if not is_ok then
break
end
var x = my_iter.item
if pred.call(x) then
break
end
end
end
end
# An iterator that maps each item to an iterator and yield
# each item from it.
class FlatMapIter[A,B]
super FunIter[A,B]
var f: Fun1[A, Iterator[B]]
protected var inner: nullable Iterator[B] = null
redef init
do
try_compute_inner
end
redef fun item
do
return inner.as(not null).item
end
redef fun is_ok
do
return inner != null
end
redef fun next
do
inner.next
if not inner.is_ok then
super
try_compute_inner
end
end
# Tries to resolve the inner iterator.
# Assigns null to `inner` if it fails.
protected fun try_compute_inner
do
inner = null
if not my_iter.is_ok then return
var res = f.call(my_iter.item)
if res.is_ok then inner = res
end
end
# An iterator that yield each item in order
class OrderedIter[E]
super FunIter[E,E]
var f: Fun1[E, Comparable]
private var sorted_iter: Iterator[E] is noinit
private var sorted_arr: Array[E] is noinit
redef init
do
sorted_arr = my_iter.to_a
sorted_arr.sort_with(f)
sorted_iter = sorted_arr.iterator
end
redef fun next
do
sorted_iter.next
end
redef fun item
do
return sorted_iter.item
end
redef fun is_ok
do
return sorted_iter.is_ok
end
redef fun finish
do
sorted_iter.finish
end
redef fun to_a
do
return sorted_arr
end
end
# Comparator that use a function provided by the user to compare between elements.
class ComparatorWith[E]
super Comparator
redef type COMPARED: E
var f: Fun1[E, Comparable]
redef fun compare(a,b)
do
var x = f.call(a)
var y = f.call(b)
if x < y then return -1
if x > y then return 1
return 0
end
end
lib/functional/iter_extras.nit:17,1--408,3