148 lines
3.8 KiB
GDScript3
148 lines
3.8 KiB
GDScript3
|
|
extends IteratorBase
|
||
|
|
class_name Iterator
|
||
|
|
|
||
|
|
## A naive iterator with additional quality-of-life utility
|
||
|
|
##
|
||
|
|
## See [IteratorBase] and [IterableBase] for more info!
|
||
|
|
|
||
|
|
## Loops over all elements within the iterable sequence
|
||
|
|
func foreach(what : Callable = func(__elem): pass):
|
||
|
|
var next_ = self.next()
|
||
|
|
while not next_ is ItEnd:
|
||
|
|
var continue_ = what.call(next_)
|
||
|
|
if continue_ == false:
|
||
|
|
break
|
||
|
|
next_ = self.next()
|
||
|
|
|
||
|
|
## Loops and enumerates an iterable sequence
|
||
|
|
func enumerate(what : Callable = func(__elem, __idx : int): pass):
|
||
|
|
var idx_ = 0
|
||
|
|
var next_ = self.next()
|
||
|
|
while not next_ is ItEnd:
|
||
|
|
var continue_ = what.call(next_, idx_)
|
||
|
|
if continue_ == false:
|
||
|
|
break
|
||
|
|
idx_ += 1
|
||
|
|
next_ = self.next()
|
||
|
|
|
||
|
|
|
||
|
|
## An iterable working on an [Array] or a relative like [PackedByteArray]
|
||
|
|
class ArrayIterable extends IterableBase:
|
||
|
|
var _x
|
||
|
|
|
||
|
|
var _start : int
|
||
|
|
var _end : int
|
||
|
|
|
||
|
|
func _init(x, start : int = 0, end : int = -1):
|
||
|
|
self._x = x
|
||
|
|
self._start = start
|
||
|
|
self._end = x.size() if end < 0 else end
|
||
|
|
|
||
|
|
if self._start < 0 or self._start > self._end or self._end > x.size():
|
||
|
|
ArgumentOutOfRangeError.raise()
|
||
|
|
return
|
||
|
|
|
||
|
|
class _Iterator extends Iterator:
|
||
|
|
var _itx
|
||
|
|
var _itstart : int
|
||
|
|
var _itend : int
|
||
|
|
|
||
|
|
var _itindex : int
|
||
|
|
|
||
|
|
func _init(x, start : int, end : int):
|
||
|
|
self._itx = x
|
||
|
|
self._itstart = start
|
||
|
|
self._itend = end
|
||
|
|
self._itindex = start
|
||
|
|
|
||
|
|
func has_next() -> bool:
|
||
|
|
return not (self._itx.is_empty() or self._itindex == self._itend)
|
||
|
|
|
||
|
|
func next() -> Variant:
|
||
|
|
if not has_next():
|
||
|
|
return ItEnd.new()
|
||
|
|
self._itindex += 1
|
||
|
|
return self._itx[self._itindex - 1]
|
||
|
|
|
||
|
|
func front() -> Variant:
|
||
|
|
return ItEnd.new() if self._itx.is_empty() else self._itx[self._itstart]
|
||
|
|
|
||
|
|
func back() -> Variant:
|
||
|
|
return ItEnd.new() if self._itx.is_empty() else self._itx[self._itend - 1]
|
||
|
|
|
||
|
|
func empty() -> bool:
|
||
|
|
return self._itx.is_empty()
|
||
|
|
|
||
|
|
func at(n : int) -> Variant:
|
||
|
|
var it = _Iterator.new(self._itx, self._itstart, self._itend)
|
||
|
|
var tmp = ItEnd.new()
|
||
|
|
for i in range(n):
|
||
|
|
tmp = it.next()
|
||
|
|
return tmp
|
||
|
|
|
||
|
|
func iter() -> Iterator:
|
||
|
|
return self._Iterator.new(self._x, self._start, self._end)
|
||
|
|
|
||
|
|
|
||
|
|
## An iterable working on a [Dictionary]
|
||
|
|
class DictionaryIterable extends IterableBase:
|
||
|
|
var _dict : Dictionary
|
||
|
|
|
||
|
|
func _init(dict : Dictionary):
|
||
|
|
self._dict = dict
|
||
|
|
|
||
|
|
class _Iterator extends Iterator:
|
||
|
|
var _itdict : Dictionary
|
||
|
|
|
||
|
|
var _itindex : int
|
||
|
|
var _itend : int
|
||
|
|
var _itkeys : Array
|
||
|
|
|
||
|
|
func _init(dict : Dictionary):
|
||
|
|
self._itdict = dict
|
||
|
|
self._itindex = 0
|
||
|
|
self._itend = dict.size()
|
||
|
|
self._itkeys = dict.keys()
|
||
|
|
|
||
|
|
func has_next() -> bool:
|
||
|
|
return not (self._itdict.is_empty() or self._itindex == self._itend)
|
||
|
|
|
||
|
|
func next() -> Variant:
|
||
|
|
if not has_next():
|
||
|
|
return ItEnd.new()
|
||
|
|
self._itindex += 1
|
||
|
|
return Tuple.new([
|
||
|
|
self._itkeys[self._itindex - 1],
|
||
|
|
self._itdict[self._itkeys[self._itindex - 1]]
|
||
|
|
])
|
||
|
|
|
||
|
|
func empty() -> bool:
|
||
|
|
return self._itdict.is_empty()
|
||
|
|
|
||
|
|
func iter() -> Iterator:
|
||
|
|
return self._Iterator.new(self._dict)
|
||
|
|
|
||
|
|
## Anonymous [IterableBase]
|
||
|
|
class _Iterable extends IterableBase:
|
||
|
|
var seq
|
||
|
|
func _init(seq_):
|
||
|
|
self.seq = seq_
|
||
|
|
func iter() -> Iterator:
|
||
|
|
return seq.iter()
|
||
|
|
|
||
|
|
## Constructs an iterable sequence of type [IterableBase] based on x.
|
||
|
|
static func to_iterable(x : Variant) -> IterableBase:
|
||
|
|
if x is Array or x is PackedByteArray or x is PackedColorArray or x is PackedFloat32Array or x is PackedFloat64Array or x is PackedInt32Array or x is PackedInt64Array or x is PackedStringArray or x is PackedVector2Array or x is PackedVector3Array:
|
||
|
|
return ArrayIterable.new(x)
|
||
|
|
if x is Dictionary:
|
||
|
|
return DictionaryIterable.new(x)
|
||
|
|
if x is IterableBase:
|
||
|
|
return x
|
||
|
|
if x.has_method("iter"):
|
||
|
|
return _Iterable.new(x)
|
||
|
|
return to_iterable([x])
|
||
|
|
|
||
|
|
## Returns an [Iterator] onto the given sequence.
|
||
|
|
static func iter(x) -> Iterator:
|
||
|
|
return to_iterable(x).iter()
|