Lazy.js is a lazy evaluation library for JavaScript.
This has been done before. For examples see:
However, at least at present, Lazy.js is faster (on average) than any of those libraries. It is also more complete, with nearly all of the functionality of Underscore and Lo-Dash.
Finding your way around the codeAt the heart of Lazy.js is the Sequence object. You create an initial sequence using Lazy, which can accept an array, object, or string. You can then "chain" together methods from this sequence, creating a new sequence with each call.
Here's an example:
var data = getReallyBigArray();
var statistics = Lazy(data)
.map(transform)
.filter(validate)
.reduce(aggregate);
Sequence is the foundation of other, more specific sequence types.
An ArrayLikeSequence provides indexed access to its elements.
An ObjectLikeSequence consists of key/value pairs.
A StringLikeSequence is like a string (duh): actually, it is an ArrayLikeSequence whose elements happen to be characters.
An AsyncSequence is special: it iterates over its elements asynchronously (so calling each
generally begins an asynchronous loop and returns immediately).
I wrote a blog post that explains a little bit more about Lazy.js, which you can read here.
You can also create an issue on GitHub if you have any issues with the library. I work through them eventually.
Lazy LazyWraps an object and returns a Sequence. For null
or undefined
, simply returns an empty sequence (see Lazy.strict for a stricter implementation).
function Lazy(source) { }
function Lazy(source) { if (isArray(source)) { return new ArrayWrapper(source); } else if (typeof source === "string") { return new StringWrapper(source); } else if (source instanceof Sequence) { return source; } if (Lazy.extensions) { var extensions = Lazy.extensions, length = extensions.length, result; while (!result && length--) { result = extensions[length](source); } if (result) { return result; } } return new ObjectWrapper(source); }Name Type(s) Description source Array|Object|string
An array, object, or string to wrap.
returns SequenceThe wrapped lazy object.
ExamplesLazy([1, 2, 4]) Lazy({ foo: "bar" }) Lazy("hello, world!") Lazy() Lazy(null)createWrapper Lazy.createWrapper
Defines a wrapper for custom StreamLikeSequences. This is useful if you want a way to handle a stream of events as a sequence, but you can't use Lazy's existing interface (i.e., you're wrapping an object from a library with its own custom events).
This method defines a factory: that is, it produces a function that can be used to wrap objects and return a Sequence. Hopefully the example will make this clear.
SignatureLazy.createWrapper = function(initializer) { }
Lazy.createWrapper = function createWrapper(initializer) { var ctor = function() { this.listeners = []; }; ctor.prototype = Object.create(StreamLikeSequence.prototype); ctor.prototype.each = function(listener) { this.listeners.push(listener); }; ctor.prototype.emit = function(data) { var listeners = this.listeners; for (var len = listeners.length, i = len - 1; i >= 0; --i) { if (listeners[i](data) === false) { listeners.splice(i, 1); } } }; return function() { var sequence = new ctor(); initializer.apply(sequence, arguments); return sequence; }; }Name Type(s) Description initializer Function
An initialization function called on objects created by this factory. this
will be bound to the created object, which is an instance of StreamLikeSequence. Use emit
to generate data for the sequence.
A function that creates a new StreamLikeSequence, initializes it using the specified function, and returns it.
Examplesvar factory = Lazy.createWrapper(function(eventSource) { var sequence = this; eventSource.handleEvent(function(data) { sequence.emit(data); }); }); var eventEmitter = { triggerEvent: function(data) { eventEmitter.eventHandler(data); }, handleEvent: function(handler) { eventEmitter.eventHandler = handler; }, eventHandler: function() {} }; var events = []; factory(eventEmitter).each(function(e) { events.push(e); }); eventEmitter.triggerEvent('foo'); eventEmitter.triggerEvent('bar'); eventsgenerate Lazy.generate
Creates a GeneratedSequence using the specified generator function and (optionally) length.
SignatureLazy.generate = function(generatorFn, length) { }
Lazy.generate = function generate(generatorFn, length) { return new GeneratedSequence(generatorFn, length); }Name Type(s) Description generatorFn function(number):*
The function used to generate the sequence. This function accepts an index as a parameter and should return a value for that index in the resulting sequence.
length number?The length of the sequence, for sequences with a definite length.
returns GeneratedSequenceThe generated sequence.
Examplesvar randomNumbers = Lazy.generate(Math.random); var countingNumbers = Lazy.generate(function(i) { return i + 1; }, 5); randomNumbers randomNumbers.length() countingNumbers countingNumbers.length()range Lazy.range
Creates a sequence from a given starting value, up to a specified stopping value, incrementing by a given step. Invalid values for any of these arguments (e.g., a step of 0) result in an empty sequence.
SignatureLazy.range = function() { }
Lazy.range = function range() { var start = arguments.length > 1 ? arguments[0] : 0, stop = arguments.length > 1 ? arguments[1] : arguments[0], step = arguments.length > 2 && arguments[2]; if (step === false) { step = stop > start ? 1 : -1; } if (step === 0) { return Lazy([]); } return Lazy.generate(function(i) { return start + (step * i); }) .take(Math.ceil((stop - start) / step)); }Name Type(s) Description returns GeneratedSequence
The sequence defined by the given ranges.
ExamplesLazy.range(3) Lazy.range(1, 4) Lazy.range(2, 10, 2) Lazy.range(5, 1, 2) Lazy.range(5, 15, -2) Lazy.range(3, 10, 3) Lazy.range(5, 2) Lazy.range(7, 2, -2) Lazy.range(3, 5, 0)repeat Lazy.repeat
Creates a sequence consisting of the given value repeated a specified number of times.
SignatureLazy.repeat = function(value, count) { }
Lazy.repeat = function repeat(value, count) { return Lazy.generate(function() { return value; }, count); }Name Type(s) Description value *
The value to repeat.
count number?The number of times the value should be repeated in the sequence. If this argument is omitted, the value will repeat forever.
returns GeneratedSequenceThe sequence containing the repeated value.
ExamplesLazy.repeat("hi", 3) Lazy.repeat("young") Lazy.repeat("young").length() Lazy.repeat("young").take(3)strict Lazy.strict
Provides a stricter version of Lazy which throws an error when attempting to wrap null
, undefined
, or numeric or boolean values as a sequence.
Lazy.strict = function() { }
Lazy.strict = function strict() { function StrictLazy(source) { if (source == null) { throw new Error("You cannot wrap null or undefined using Lazy."); } if (typeof source === "number" || typeof source === "boolean") { throw new Error("You cannot wrap primitive values using Lazy."); } return Lazy(source); }; Lazy(Lazy).each(function(property, name) { StrictLazy[name] = property; }); return StrictLazy; }Name Type(s) Description returns Function
A stricter version of the Lazy helper function.
Examplesvar Strict = Lazy.strict(); Strict() Strict(null) Strict(true) Strict(5) Strict([1, 2, 3]) Strict({ foo: "bar" }) Strict("hello, world!") Strict.range(3) Strict.generate(Date.now)Sequence Sequence
The Sequence
object provides a unified API encapsulating the notion of zero or more consecutive elements in a collection, stream, etc.
Generally speaking, creating a sequence should not be an expensive operation, and should not iterate over an underlying source or trigger any side effects. This means that chaining together methods that return sequences incurs only the cost of creating the Sequence
objects themselves and not the cost of iterating an underlying data source multiple times.
The following code, for example, creates 4 sequences and does nothing with source
:
var seq = Lazy(source)
.map(func)
.filter(pred)
.reverse();
Lazy's convention is to hold off on iterating or otherwise doing anything (aside from creating Sequence
objects) until you call each
:
seq.each(function(x) { console.log(x); });
Defining custom sequences
Defining your own type of sequence is relatively simple:
init
, this function will be called upon initialization.getIterator
method or an each
method. The former supports both asynchronous and synchronous iteration, but is slightly more cumbersome to implement. The latter supports synchronous iteration and can be automatically implemented in terms of the former. You can also implement both if you want, e.g. to optimize performance. For more info, see Iterator and AsyncSequence.As a trivial example, the following code defines a new method, sample
, which randomly may or may not include each element from its parent.
Lazy.Sequence.define("sample", {
each: function(fn) {
return this.parent.each(function(e) {
if (Math.random() > 0.5) {
return fn(e);
}
});
}
});
(Of course, the above could also easily have been implemented using #filter instead of creating a custom sequence. But I did say this was a trivial example, to be fair.)
Now it will be possible to create this type of sequence from any parent sequence by calling the method name you specified. In other words, you can now do this:
Lazy(arr).sample();
Lazy(arr).map(func).sample();
Lazy(arr).map(func).filter(pred).sample();
Etc., etc.
define Sequence.defineCreate a new constructor function for a type inheriting from Sequence
.
Sequence.define = function(methodName, overrides) { }
Sequence.define = function define(methodName, overrides) { if (!overrides || (!overrides.getIterator && !overrides.each)) { throw new Error("A custom sequence must implement *at least* getIterator or each!"); } return defineSequenceType(Sequence, methodName, overrides); }Name Type(s) Description methodName string|Array.<string>
The name(s) of the method(s) to be used for constructing the new sequence. The method will be attached to the Sequence
prototype so that it can be chained with any other sequence methods, like #map, #filter, etc.
An object containing function overrides for this new sequence type. Must include either getIterator
or each
(or both). May include an init
method as well. For these overrides, this
will be the new sequence, and this.parent
will be the base sequence from which the new sequence was constructed.
A constructor for a new type inheriting from Sequence
.
Lazy.Sequence.define("verbose", { init: function(logger) { this.logger = logger; }, each: function(fn) { var logger = this.logger; return this.parent.each(function(e, i) { logger(e); return fn(e, i); }); } }); Lazy([1, 2, 3]).verbose(logger).each(Lazy.noop)async Sequence#async
Creates a sequence, with the same elements as this one, that will be iterated over asynchronously when calling each
.
Sequence.async = function(interval) { }
Sequence.async = function async(interval) { return new AsyncSequence(this, interval); }Name Type(s) Description interval number?
The approximate period, in milliseconds, that should elapse between each element in the resulting sequence. Omitting this argument will result in the fastest possible asynchronous iteration.
returns AsyncSequenceThe new asynchronous sequence.
ExamplesLazy([1, 2, 3]).async(100).each(fn)chunk Sequence#chunk
Breaks this sequence into chunks (arrays) of a specified length.
SignatureSequence.chunk = function(size) { }
Sequence.chunk = function chunk(size) { if (size < 1) { throw new Error("You must specify a positive chunk size."); } return new ChunkedSequence(this, size); }Name Type(s) Description size number
The size of each chunk.
returns SequenceThe resulting sequence of chunks.
ExamplesLazy([]).chunk(2) Lazy([1, 2, 3]).chunk(2) Lazy([1, 2, 3]).chunk(1) Lazy([1, 2, 3]).chunk(4) Lazy([1, 2, 3]).chunk(0)compact Sequence#compact
Creates a new sequence with the same elements as this one, except for all falsy values (false
, 0
, ""
, null
, and undefined
).
Sequence.compact = function() { }
Sequence.compact = function compact() { return this.filter(function(e) { return !!e; }); }Name Type(s) Description returns Sequence
The new sequence.
ExamplesLazy(["foo", null, "bar", undefined]).compact()concat Sequence#concat
Creates a new sequence with all of the elements of this one, plus those of the given array(s).
SignatureSequence.concat = function(var_args) { }
Sequence.concat = function concat(var_args) { return new ConcatenatedSequence(this, arraySlice.call(arguments, 0)); }Name Type(s) Description var_args ...*
One or more values (or arrays of values) to use for additional items after this sequence.
returns SequenceThe new sequence.
Examplesvar left = [1, 2, 3]; var right = [4, 5, 6]; Lazy(left).concat(right) Lazy(left).concat(Lazy(right)) Lazy(left).concat(right, [7, 8]) Lazy(left).concat([4, [5, 6]]) Lazy(left).concat(Lazy([4, [5, 6]]))consecutive Sequence#consecutive
Groups this sequence into consecutive (overlapping) segments of a specified length. If the underlying sequence has fewer elements than the specified length, then this sequence will be empty.
SignatureSequence.consecutive = function(length) { }
Sequence.consecutive = function consecutive(count) { return new ConsecutiveSequence(this, count); }Name Type(s) Description length number
The length of each consecutive segment.
returns SequenceThe resulting sequence of consecutive segments.
Examplesfunction sum(vals) { return Lazy(vals).sum(); } var pairs = Lazy([1, 2, 3, 4]).consecutive(2); pairs.map(sum) pairs.map(sum) Lazy([]).consecutive(2) Lazy([1]).consecutive(2) Lazy([1, 2]).consecutive(2) Lazy([1, 2, 3]).consecutive(2) Lazy([1, 2, 3]).consecutive(0) Lazy([1, 2, 3]).consecutive(1)contains Sequence#contains
Checks whether the given value is in this sequence.
SignatureSequence.contains = function(value, equalityFn) { }
Sequence.contains = function contains(value, equalityFn) { return this.indexOf(value, equalityFn) !== -1; }Name Type(s) Description value *
The element to search for in the sequence.
equalityFn Function?An optional equality function, which should take two arguments and return true or false to indicate whether those values are considered equal.
returns booleanTrue if the sequence contains the value, false if not.
Examplesvar numbers = [5, 10, 15, 20]; Lazy(numbers).contains(15) Lazy(numbers).contains(13)countBy Sequence#countBy
Creates a new ObjectLikeSequence containing the unique keys of all the elements in this sequence, each paired with the number of elements in this sequence having that key.
SignatureSequence.countBy = function(keyFn) { }
Sequence.countBy = function countBy(keyFn) { return new CountedSequence(this, keyFn); }Name Type(s) Description keyFn Function|string
The function to call on the elements in this sequence to obtain a key by which to count them, or a string representing a parameter to read from all the elements in this sequence.
returns SequenceThe new sequence.
Examplesfunction oddOrEven(x) { return x % 2 === 0 ? 'even' : 'odd'; } var numbers = [1, 2, 3, 4, 5]; Lazy(numbers).countBy(oddOrEven) Lazy(numbers).countBy(oddOrEven).get("odd") Lazy(numbers).countBy(oddOrEven).get("foo")dropWhile Sequence#dropWhile
aliases: skipWhile
Creates a new sequence comprising the elements from this sequence after those that satisfy some predicate. The sequence starts with the first element that does not match the predicate.
SignatureSequence.dropWhile = function(predicate) { }
Sequence.dropWhile = function dropWhile(predicate) { return new DropWhileSequence(this, predicate); }Name Type(s) Description predicate Function returns Sequence
The new sequence
each Sequence#eachaliases: forEach
Iterates over this sequence and executes a function for every element.
SignatureSequence.each = function(fn) { }
Sequence.each = function each(fn) { var iterator = this.getIterator(), i = -1; while (iterator.moveNext()) { if (fn(iterator.current(), ++i) === false) { return false; } } return true; }Name Type(s) Description fn Function
The function to call on each element in the sequence. Return false from the function to end the iteration.
returns booleantrue
if the iteration evaluated the entire sequence, or false
if iteration was ended early.
Lazy([1, 2, 3, 4]).each(fn)equals Sequence#equals
Compare this to another sequence for equality.
SignatureSequence.equals = function(other, equalityFn) { }
Sequence.equals = function equals(other, equalityFn) { if (!(other instanceof Sequence)) { return false; } var it = this.getIterator(), oit = other.getIterator(), eq = equalityFn || Lazy.equality; while (it.moveNext()) { if (!oit.moveNext()) { return false; } if (!eq(it.current(), oit.current())) { return false; } } return !oit.moveNext(); }Name Type(s) Description other Sequence
The other sequence to compare this one to.
equalityFn Function?An optional equality function, which should take two arguments and return true or false to indicate whether those values are considered equal.
returns booleanWhether the two sequences contain the same values in the same order.
ExamplesLazy([1, 2]).equals(Lazy([1, 2])) Lazy([1, 2]).equals(Lazy([2, 1])) Lazy([1]).equals(Lazy([1, 2])) Lazy([1, 2]).equals(Lazy([1])) Lazy([]).equals(Lazy([])) Lazy(['foo']).equals(Lazy(['foo'])) Lazy(['1']).equals(Lazy([1])) Lazy([false]).equals(Lazy([0])) Lazy([1, 2]).equals([1, 2]) Lazy([1, 2]).equals('[1, 2]')every Sequence#every
aliases: all
Checks whether every element in this sequence satisfies a given predicate.
SignatureSequence.every = function(predicate) { }
Sequence.every = function every(predicate) { predicate = createCallback(predicate); return this.each(function(e, i) { return !!predicate(e, i); }); }Name Type(s) Description predicate Function
A function to call on (potentially) every element in this sequence.
returns booleanTrue if predicate
returns true for every element in the sequence (or the sequence is empty). False if predicate
returns false for at least one element.
var numbers = [1, 2, 3, 4, 5]; var objects = [{ foo: true }, { foo: false, bar: true }]; Lazy(numbers).every(isEven) Lazy(numbers).every(isPositive) Lazy(objects).all('foo') Lazy(objects).all('bar')filter Sequence#filter
aliases: select
Creates a new sequence whose values are the elements of this sequence which satisfy the specified predicate.
SignatureSequence.filter = function(filterFn) { }
Sequence.filter = function filter(filterFn) { return new FilteredSequence(this, createCallback(filterFn)); }Name Type(s) Description filterFn Function
The predicate to call on each element in this sequence, which returns true if the element should be included.
returns SequenceThe new sequence.
Examplesvar numbers = [1, 2, 3, 4, 5, 6]; Lazy(numbers).filter(isEven)Benchmarks
function isEven(x) { return x % 2 === 0; } var smArr = Lazy.range(10).toArray(), lgArr = Lazy.range(100).toArray(); Lazy(smArr).filter(isEven).each(Lazy.noop) Lazy(lgArr).filter(isEven).each(Lazy.noop) _.each(_.filter(smArr, isEven), _.noop) _.each(_.filter(lgArr, isEven), _.noop)Implementation 10 elements 100 elements lazy lodash find Sequence#find
aliases: detect
Seaches for the first element in the sequence satisfying a given predicate.
SignatureSequence.find = function(predicate) { }
Sequence.find = function find(predicate) { return this.filter(predicate).first(); }Name Type(s) Description predicate Function
A function to call on (potentially) every element in the sequence.
returns *The first element in the sequence for which predicate
returns true
, or undefined
if no such element is found.
function divisibleBy3(x) { return x % 3 === 0; } var numbers = [5, 6, 7, 8, 9, 10]; Lazy(numbers).find(divisibleBy3) Lazy(numbers).find(isNegative)findWhere Sequence#findWhere
Returns the first element in this sequence with property names and values matching those of the specified object.
SignatureSequence.findWhere = function(properties) { }
Sequence.findWhere = function findWhere(properties) { return this.where(properties).first(); }Name Type(s) Description properties Object
The properties that should be found on some element in this sequence.
returns *The found element, or undefined
if none exists in this sequence.
var words = ["foo", "bar"]; Lazy(words).findWhere({ 0: "f" }); Lazy(words).findWhere({ 0: "z" });first Sequence#first
aliases: head take
Creates a new sequence comprising the first N elements from this sequence, OR (if N is undefined
) simply returns the first element of this sequence.
Sequence.first = function(count) { }
Sequence.first = function first(count) { if (typeof count === "undefined") { return getFirst(this); } return new TakeSequence(this, count); }Name Type(s) Description count number?
The number of elements to take from this sequence. If this value exceeds the length of the sequence, the resulting sequence will be essentially the same as this one.
returns *The new sequence (or the first element from this sequence if no count was given).
Examplesfunction powerOfTwo(exp) { return Math.pow(2, exp); } Lazy.generate(powerOfTwo).first() Lazy.generate(powerOfTwo).first(5) Lazy.generate(powerOfTwo).skip(2).first() Lazy.generate(powerOfTwo).skip(2).first(2)flatten Sequence#flatten
Creates a new sequence with every element from this sequence, and with arrays exploded so that a sequence of arrays (of arrays) becomes a flat sequence of values.
SignatureSequence.flatten = function(shallow) { }
Sequence.flatten = function flatten(shallow) { return new FlattenedSequence(this, shallow); }Name Type(s) Description shallow boolean
Option to flatten only one level deep (default is recursive).
returns SequenceThe new sequence.
ExamplesLazy([1, [2, 3], [4, [5]]]).flatten() Lazy([1, [2, 3], [4, [5]]]).flatten(true) Lazy([1, Lazy([2, 3])]).flatten()get Sequence#get
Returns the element at the specified index. Note that, for sequences that are not ArrayLikeSequences, this may require partially evaluating the sequence, iterating to reach the result. (In other words for such sequences this method is not O(1).)
SignatureSequence.get = function(i) { }
Sequence.get = function get(i) { var element; this.each(function(e, index) { if (index === i) { element = e; return false; } }); return element; }Name Type(s) Description i number
The index to access.
returns *The element.
getIterator Sequence#getIteratorCreates an Iterator object with two methods, moveNext
-- returning true or false -- and current
-- returning the current value.
This method is used when asynchronously iterating over sequences. Any type inheriting from Sequence
must implement this method or it can't support asynchronous iteration.
Note that this method is not intended to be used directly by application code. Rather, it is intended as a means for implementors to potentially define custom sequence types that support either synchronous or asynchronous iteration.
SignatureSequence.getIterator = function() { }
Sequence.getIterator = function getIterator() { return new Iterator(this); }Name Type(s) Description returns Iterator
An iterator object.
Examplesvar iterator = Lazy([1, 2]).getIterator(); iterator.moveNext(); iterator.current(); iterator.moveNext(); iterator.current(); iterator.moveNext();groupBy Sequence#groupBy
Creates a new ObjectLikeSequence comprising the elements in this one, grouped together according to some key. The value associated with each key in the resulting object-like sequence is an array containing all of the elements in this sequence with that key.
SignatureSequence.groupBy = function(keyFn, valFn) { }
Sequence.groupBy = function groupBy(keyFn, valFn) { return new GroupedSequence(this, keyFn, valFn); }Name Type(s) Description keyFn Function|string
The function to call on the elements in this sequence to obtain a key by which to group them, or a string representing a parameter to read from all the elements in this sequence.
valFn Function|string(Optional) The function to call on the elements in this sequence to assign to the value for each instance to appear in the group, or a string representing a parameter to read from all the elements in this sequence.
returns ObjectLikeSequenceThe new sequence.
Examplesfunction oddOrEven(x) { return x % 2 === 0 ? 'even' : 'odd'; } function square(x) { return x*x; } var numbers = [1, 2, 3, 4, 5]; Lazy(numbers).groupBy(oddOrEven) Lazy(numbers).groupBy(oddOrEven).get("odd") Lazy(numbers).groupBy(oddOrEven).get("foo") Lazy(numbers).groupBy(oddOrEven, square).get("even") Lazy([ { name: 'toString' }, { name: 'toString' } ]).groupBy('name'); 'toString': [ { name: 'toString' }, { name: 'toString' } ] }indexBy Sequence#indexBy
Creates a new ObjectLikeSequence comprising the elements in this one, indexed according to some key.
SignatureSequence.indexBy = function(keyFn, valFn) { }
Sequence.indexBy = function(keyFn, valFn) { return new IndexedSequence(this, keyFn, valFn); }Name Type(s) Description keyFn Function|string
The function to call on the elements in this sequence to obtain a key by which to index them, or a string representing a property to read from all the elements in this sequence.
valFn Function|string(Optional) The function to call on the elements in this sequence to assign to the value of the indexed object, or a string representing a parameter to read from all the elements in this sequence.
returns SequenceThe new sequence.
Examplesvar people = [ { name: 'Bob', age: 25 }, { name: 'Fred', age: 34 } ]; var bob = people[0], fred = people[1]; Lazy(people).indexBy('name') Lazy(people).indexBy('name', 'age')indexOf Sequence#indexOf
Performs (at worst) a linear search from the head of this sequence, returning the first index at which the specified value is found.
SignatureSequence.indexOf = function(value, equalityFn) { }
Sequence.indexOf = function indexOf(value, equalityFn) { var eq = equalityFn || Lazy.equality, foundIndex = -1; this.each(function(e, i) { if (eq(e, value)) { foundIndex = i; return false; } }); return foundIndex; }Name Type(s) Description value *
The element to search for in the sequence.
equalityFn Function?An optional equality function, which should take two arguments and return true or false to indicate whether those values are considered equal.
returns numberThe index within this sequence where the given value is located, or -1 if the sequence doesn't contain the value.
Examplesfunction reciprocal(x) { return 1 / x; } Lazy(["foo", "bar", "baz"]).indexOf("bar") Lazy([1, 2, 3]).indexOf(4) Lazy([1, 2, 3]).map(reciprocal).indexOf(0.5)initial Sequence#initial
Creates a new sequence comprising all but the last N elements of this sequence.
SignatureSequence.initial = function(count) { }
Sequence.initial = function initial(count) { return new InitialSequence(this, count); }Name Type(s) Description count number?
The number of items to omit from the end of the sequence (defaults to 1).
returns SequenceThe new sequence.
ExamplesLazy([1, 2, 3, 4]).initial() Lazy([1, 2, 3, 4]).initial(2) Lazy([1, 2, 3]).filter(Lazy.identity).initial()intersection Sequence#intersection
Creates a new sequence with all the elements of this sequence that also appear among the specified arguments.
SignatureSequence.intersection = function(var_args) { }
Sequence.intersection = function intersection(var_args) { if (arguments.length === 1 && isArray(arguments[0])) { return new SimpleIntersectionSequence(this, ( var_args)); } else { return new IntersectionSequence(this, arraySlice.call(arguments, 0)); } }Name Type(s) Description var_args ...*
The values, or array(s) of values, in which elements from this sequence must also be included to end up in the resulting sequence.
returns SequenceThe new sequence.
ExamplesLazy(["foo", "bar"]).intersection([]) Lazy(["foo", "bar"]).intersection(["bar", "baz"]) Lazy(["a", "a"]).intersection(["a"]) Lazy(["a"]).intersection(["a", "a"]) Lazy(["a", "a"]).intersection(["a", "a"]) Lazy(["a", "a"]).intersection(["a"], ["a"])invoke Sequence#invoke
Creates a new sequence whose values are calculated by invoking the specified function on each element in this sequence.
SignatureSequence.invoke = function(methodName) { }
Sequence.invoke = function invoke(methodName) { return this.map(function(e) { return e[methodName](); }); }Name Type(s) Description methodName string
The name of the method to invoke for every element in this sequence.
returns SequenceThe new sequence.
Examplesfunction Person(first, last) { this.fullName = function fullName() { return first + " " + last; }; } var people = [ new Person("Dan", "Tao"), new Person("Bob", "Smith") ]; Lazy(people).invoke("fullName")isEmpty Sequence#isEmpty
Checks whether the sequence has no elements.
SignatureSequence.isEmpty = function() { }
Sequence.isEmpty = function isEmpty() { return !this.any(); }Name Type(s) Description returns boolean
True if the sequence is empty, false if it contains at least one element.
ExamplesLazy([]).isEmpty() Lazy([1, 2, 3]).isEmpty()join Sequence#join
aliases: toString
Creates a string from joining together all of the elements in this sequence, separated by the given delimiter.
SignatureSequence.join = function(delimiter) { }
Sequence.join = function join(delimiter) { delimiter = typeof delimiter === "undefined" ? "," : String(delimiter); var i = -1; return this.reduce(function(str, e) { if (++i > 0) { str += delimiter; } return str + e; }, ""); }Name Type(s) Description delimiter string?
The separator to insert between every element from this sequence in the resulting string (defaults to ","
).
The delimited string.
Examplesfunction toParam(v, k) { return k + '=' + v; } Lazy([6, 29, 1984]).join("/") Lazy(["a", "b", "c"]).join() Lazy(["a", "b", "c"]).join("") Lazy([1, 2, 3]).join() Lazy([1, 2, 3]).join("") Lazy(["", "", ""]).join(",") Lazy([1, 2]).join(0) Lazy(["cons", "d"]).join(true) Lazy({foo: 1, bar: 2}).values().join() Lazy({foo: 1, bar: 2}).keys().join() Lazy({foo: 1, bar: 2}).map(toParam).join('&')last Sequence#last
Creates a new sequence comprising the last N elements of this sequence, OR (if N is undefined
) simply returns the last element of this sequence.
Sequence.last = function(count) { }
Sequence.last = function last(count) { if (typeof count === "undefined") { return this.reverse().first(); } return this.reverse().take(count).reverse(); }Name Type(s) Description count number?
The number of items to take from the end of the sequence.
returns *The new sequence (or the last element from this sequence if no count was given).
ExamplesLazy([1, 2, 3]).last() Lazy([1, 2, 3]).last(2) Lazy([1, 2, 3]).filter(isEven).last(2)lastIndexOf Sequence#lastIndexOf
Performs (at worst) a linear search from the tail of this sequence, returning the last index at which the specified value is found.
SignatureSequence.lastIndexOf = function(value) { }
Sequence.lastIndexOf = function lastIndexOf(value, equalityFn) { var reversed = this.getIndex().reverse(), index = reversed.indexOf(value, equalityFn); if (index !== -1) { index = reversed.length() - index - 1; } return index; }Name Type(s) Description value *
The element to search for in the sequence.
returns numberThe last index within this sequence where the given value is located, or -1 if the sequence doesn't contain the value.
ExamplesLazy(["a", "b", "c", "b", "a"]).lastIndexOf("b") Lazy([1, 2, 3]).lastIndexOf(0) Lazy([2, 2, 1, 2, 4]).filter(isEven).lastIndexOf(2)map Sequence#map
aliases: collect
Creates a new sequence whose values are calculated by passing this sequence's elements through some mapping function.
SignatureSequence.map = function(mapFn) { }
Sequence.map = function map(mapFn) { return new MappedSequence(this, createCallback(mapFn)); }Name Type(s) Description mapFn Function
The mapping function used to project this sequence's elements onto a new sequence. This function takes up to two arguments: the element, and the current index.
returns SequenceThe new sequence.
Examplesfunction addIndexToValue(e, i) { return e + i; } Lazy([]).map(increment) Lazy([1, 2, 3]).map(increment) Lazy([1, 2, 3]).map(addIndexToValue)Benchmarks
function increment(x) { return x + 1; } var smArr = Lazy.range(10).toArray(), lgArr = Lazy.range(100).toArray(); Lazy(smArr).map(increment).each(Lazy.noop) Lazy(lgArr).map(increment).each(Lazy.noop) _.each(_.map(smArr, increment), _.noop) _.each(_.map(lgArr, increment), _.noop)Implementation 10 elements 100 elements lazy lodash max Sequence#max
Gets the maximum value in the sequence.
SignatureSequence.max = function(valueFn) { }
Sequence.max = function max(valueFn) { if (typeof valueFn !== "undefined") { return this.maxBy(valueFn); } return this.reduce(function(prev, current, i) { if (typeof prev === "undefined") { return current; } return current > prev ? current : prev; }); }Name Type(s) Description valueFn Function?
The function by which the value for comparison is calculated for each element in the sequence.
returns *The element with the highest value in the sequence, or undefined if the sequence is empty.
Examplesfunction reverseDigits(x) { return Number(String(x).split('').reverse().join('')); } Lazy([]).max() Lazy([1]).max() Lazy([1, 2]).max() Lazy([2, 1]).max() Lazy([6, 18, 2, 48, 29]).max() Lazy([6, 18, 2, 48, 29]).max(reverseDigits) Lazy(['b', 'c', 'a']).max()memoize Sequence#memoize
Provides an indexed, memoized view into the sequence. This will cache the result whenever the sequence is first iterated, so that subsequent iterations will access the same element objects.
SignatureSequence.memoize = function() { }
Sequence.memoize = function memoize() { return new MemoizedSequence(this); }Name Type(s) Description returns ArrayLikeSequence
An indexed, memoized sequence containing this sequence's elements, cached after the first iteration.
Examplesfunction createObject() { return new Object(); } var plain = Lazy.generate(createObject, 10), memoized = Lazy.generate(createObject, 10).memoize(); plain.toArray()[0] === plain.toArray()[0]; memoized.toArray()[0] === memoized.toArray()[0];min Sequence#min
Gets the minimum value in the sequence.
SignatureSequence.min = function(valueFn) { }
Sequence.min = function min(valueFn) { if (typeof valueFn !== "undefined") { return this.minBy(valueFn); } return this.reduce(function(prev, current, i) { if (typeof prev === "undefined") { return current; } return current < prev ? current : prev; }); }Name Type(s) Description valueFn Function?
The function by which the value for comparison is calculated for each element in the sequence.
returns *The element with the lowest value in the sequence, or undefined` if the sequence is empty.
Examplesfunction negate(x) { return x * -1; } Lazy([]).min() Lazy([1]).min() Lazy([1, 2]).min() Lazy([2, 1]).min() Lazy([6, 18, 2, 49, 34]).min() Lazy([6, 18, 2, 49, 34]).min(negate) Lazy(['b', 'a', 'c']).min()none Sequence#none
Checks whether NO elements in this sequence satisfy the given predicate (the opposite of Sequence#all, basically).
SignatureSequence.none = function(predicate) { }
Sequence.none = function none(predicate) { return !this.any(predicate); }Name Type(s) Description predicate Function?
A function to call on (potentially) every element in this sequence.
returns booleanTrue if predicate
does not return true for any element in the sequence. False if predicate
returns true for at least one element.
var numbers = [1, 2, 3, 4, 5]; Lazy(numbers).none() Lazy(numbers).none(isEven) Lazy(numbers).none(isNegative) Lazy([]).none(isEven) Lazy([]).none(isNegative) Lazy([]).none()ofType Sequence#ofType
Creates a new sequence whose values have the specified type, as determined by the typeof
operator.
Sequence.ofType = function(type) { }
Sequence.ofType = function ofType(type) { return this.filter(function(e) { return typeof e === type; }); }Name Type(s) Description type string
The type of elements to include from the underlying sequence, i.e. where typeof [element] === [type]
.
The new sequence, comprising elements of the specified type.
ExamplesLazy([1, 2, 'foo', 'bar']).ofType('number') Lazy([1, 2, 'foo', 'bar']).ofType('string') Lazy([1, 2, 'foo', 'bar']).ofType('boolean')pluck Sequence#pluck
Creates a new sequence whose values are calculated by accessing the specified property from each element in this sequence.
SignatureSequence.pluck = function(propertyName) { }
Sequence.pluck = function pluck(property) { return this.map(property); }Name Type(s) Description propertyName string
The name of the property to access for every element in this sequence.
returns SequenceThe new sequence.
Examplesvar people = [ { first: "Dan", last: "Tao" }, { first: "Bob", last: "Smith" } ]; Lazy(people).pluck("last")reduce Sequence#reduce
aliases: inject foldl
Aggregates a sequence into a single value according to some accumulator function.
For an asynchronous sequence, instead of immediately returning a result (which it can't, obviously), this method returns an AsyncHandle whose onComplete
method can be called to supply a callback to handle the final result once iteration has completed.
Sequence.reduce = function(aggregator, memo) { }
Sequence.reduce = function reduce(aggregator, memo) { if (arguments.length < 2) { return this.tail().reduce(aggregator, this.head()); } var eachResult = this.each(function(e, i) { memo = aggregator(memo, e, i); }); if (eachResult instanceof AsyncHandle) { return eachResult.then(function() { return memo; }); } return memo; }Name Type(s) Description aggregator Function
The function through which to pass every element in the sequence. For every element, the function will be passed the total aggregated result thus far and the element itself, and should return a new aggregated result.
memo *?The starting value to use for the aggregated result (defaults to the first element in the sequence).
returns *The result of the aggregation, or, for asynchronous sequences, an AsyncHandle whose onComplete
method accepts a callback to handle the final result.
function multiply(x, y) { return x * y; } var numbers = [1, 2, 3, 4]; Lazy(numbers).reduce(multiply) Lazy(numbers).reduce(multiply, 5)reduceRight Sequence#reduceRight
aliases: foldr
Aggregates a sequence, from the tail, into a single value according to some accumulator function.
SignatureSequence.reduceRight = function(aggregator, memo) { }
Sequence.reduceRight = function reduceRight(aggregator, memo) { if (arguments.length < 2) { return this.initial(1).reduceRight(aggregator, this.last()); } var indexed = this.getIndex(), i = indexed.length() - 1; return indexed.reverse().reduce(function(m, e) { return aggregator(m, e, i--); }, memo); }Name Type(s) Description aggregator Function
The function through which to pass every element in the sequence. For every element, the function will be passed the total aggregated result thus far and the element itself, and should return a new aggregated result.
memo *The starting value to use for the aggregated result.
returns *The result of the aggregation.
Examplesfunction append(s1, s2) { return s1 + s2; } function isVowel(str) { return "aeiou".indexOf(str) !== -1; } Lazy("abcde").reduceRight(append) Lazy("abcde").filter(isVowel).reduceRight(append)reject Sequence#reject
Creates a new sequence whose values exclude the elements of this sequence identified by the specified predicate.
SignatureSequence.reject = function(rejectFn) { }
Sequence.reject = function reject(rejectFn) { rejectFn = createCallback(rejectFn); return this.filter(function(e) { return !rejectFn(e); }); }Name Type(s) Description rejectFn Function
The predicate to call on each element in this sequence, which returns true if the element should be omitted.
returns SequenceThe new sequence.
ExamplesLazy([1, 2, 3, 4, 5]).reject(isEven) Lazy([{ foo: 1 }, { bar: 2 }]).reject('foo') Lazy([{ foo: 1 }, { foo: 2 }]).reject({ foo: 2 })rest Sequence#rest
aliases: skip tail rest
Creates a new sequence comprising all but the first N elements of this sequence.
SignatureSequence.rest = function(count) { }
Sequence.rest = function rest(count) { return new DropSequence(this, count); }Name Type(s) Description count number?
The number of items to omit from the beginning of the sequence (defaults to 1).
returns SequenceThe new sequence.
ExamplesLazy([1, 2, 3, 4]).rest() Lazy([1, 2, 3, 4]).rest(0) Lazy([1, 2, 3, 4]).rest(2) Lazy([1, 2, 3, 4]).rest(5)reverse Sequence#reverse
Creates a new sequence with the same elements as this one, but to be iterated in the opposite order.
Note that in some (but not all) cases, the only way to create such a sequence may require iterating the entire underlying source when each
is called.
Sequence.reverse = function() { }
Sequence.reverse = function reverse() { return new ReversedSequence(this); }Name Type(s) Description returns Sequence
The new sequence.
ExamplesLazy([1, 2, 3]).reverse() Lazy([]).reverse()shuffle Sequence#shuffle
Creates a new sequence with the same elements as this one, in a randomized order.
SignatureSequence.shuffle = function() { }
Sequence.shuffle = function shuffle() { return new ShuffledSequence(this); }Name Type(s) Description returns Sequence
The new sequence.
ExamplesLazy([1, 2, 3, 4, 5]).shuffle().value() Lazy([]).shuffle().value() Lazy([1]).shuffle().each(Lazy.noop) Lazy([]).shuffle().each(Lazy.noop)size Sequence#size
Gets the number of elements in the sequence. In some cases, this may require eagerly evaluating the sequence.
SignatureSequence.size = function() { }
Sequence.size = function size() { return this.getIndex().length(); }Name Type(s) Description returns number
The number of elements in the sequence.
ExamplesLazy([1, 2, 3]).size(); Lazy([1, 2]).map(Lazy.identity).size(); Lazy([1, 2, 3]).reject(isEven).size(); Lazy([1, 2, 3]).take(1).size(); Lazy({ foo: 1, bar: 2 }).size(); Lazy('hello').size();some Sequence#some
aliases: any
Checks whether at least one element in this sequence satisfies a given predicate (or, if no predicate is specified, whether the sequence contains at least one element).
SignatureSequence.some = function(predicate) { }
Sequence.some = function some(predicate) { predicate = createCallback(predicate, true); var success = false; this.each(function(e) { if (predicate(e)) { success = true; return false; } }); return success; }Name Type(s) Description predicate Function?
A function to call on (potentially) every element in this sequence.
returns booleanTrue if predicate
returns true for at least one element in the sequence. False if predicate
returns false for every element (or the sequence is empty).
var numbers = [1, 2, 3, 4, 5]; Lazy(numbers).some() Lazy(numbers).some(isEven) Lazy(numbers).some(isNegative) Lazy([]).some()sort Sequence#sort
Creates a new sequence with the same elements as this one, but ordered using the specified comparison function.
This has essentially the same behavior as calling Array#sort
, but obviously instead of modifying the collection it returns a new Sequence object.
Sequence.sort = function(sortFn, descending) { }
Sequence.sort = function sort(sortFn, descending) { sortFn || (sortFn = compare); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }Name Type(s) Description sortFn Function?
The function used to compare elements in the sequence. The function will be passed two elements and should return:
- 1 if the first is greater
- -1 if the second is greater
- 0 if the two values are the same
descending boolean
Whether or not the resulting sequence should be in descending order (defaults to false
).
The new sequence.
ExamplesLazy([5, 10, 1]).sort() Lazy(['foo', 'bar']).sort() Lazy(['b', 'c', 'a']).sort(null, true) Lazy([5, 10, 1]).sort(null, true) Lazy(['a', 'ab', 'aa', 'ba', 'b', 'abc']).sort(function compare(x, y) { if (x.length && (x.length !== y.length)) { return compare(x.length, y.length); } if (x === y) { return 0; } return x > y ? 1 : -1; });sortBy Sequence#sortBy
Creates a new sequence with the same elements as this one, but ordered by the results of the given function.
You can pass:
Sequence.sortBy = function(sortFn, descending) { }
Sequence.sortBy = function sortBy(sortFn, descending) { sortFn = createComparator(sortFn); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }Name Type(s) Description sortFn Function
The function to call on the elements in this sequence, in order to sort them.
descending booleanWhether or not the resulting sequence should be in descending order (defaults to false
).
The new sequence.
Examplesfunction population(country) { return country.pop; } function area(country) { return country.sqkm; } var countries = [ { name: "USA", pop: 320000000, sqkm: 9600000 }, { name: "Brazil", pop: 194000000, sqkm: 8500000 }, { name: "Nigeria", pop: 174000000, sqkm: 924000 }, { name: "China", pop: 1350000000, sqkm: 9700000 }, { name: "Russia", pop: 143000000, sqkm: 17000000 }, { name: "Australia", pop: 23000000, sqkm: 7700000 } ]; Lazy(countries).sortBy(population).last(3).pluck('name') Lazy(countries).sortBy(area).last(3).pluck('name') Lazy(countries).sortBy(area, true).first(3).pluck('name')Benchmarks
var randoms = Lazy.generate(Math.random).take(100).toArray(); Lazy(randoms).sortBy(Lazy.identity).each(Lazy.noop) _.each(_.sortBy(randoms, Lazy.identity), _.noop)Implementation Ops/second lazy lodash sortedIndex Sequence#sortedIndex
Performs a binary search of this sequence, returning the lowest index where the given value is either found, or where it belongs (if it is not already in the sequence).
This method assumes the sequence is in sorted order and will fail otherwise.
SignatureSequence.sortedIndex = function(value) { }
Sequence.sortedIndex = function sortedIndex(value) { var indexed = this.getIndex(), lower = 0, upper = indexed.length(), i; while (lower < upper) { i = (lower + upper) >>> 1; if (compare(indexed.get(i), value) === -1) { lower = i + 1; } else { upper = i; } } return lower; }Name Type(s) Description value *
The element to search for in the sequence.
returns numberAn index within this sequence where the given value is located, or where it belongs in sorted order.
ExamplesLazy([1, 3, 6, 9]).sortedIndex(3) Lazy([1, 3, 6, 9]).sortedIndex(7) Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(10) Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(12)sum Sequence#sum
Gets the sum of the numeric values in the sequence.
SignatureSequence.sum = function(valueFn) { }
Sequence.sum = function sum(valueFn) { if (typeof valueFn !== "undefined") { return this.sumBy(valueFn); } return this.reduce(function(x, y) { return x + y; }, 0); }Name Type(s) Description valueFn Function?
The function used to select the numeric values that will be summed up.
returns *The sum.
ExamplesLazy([]).sum() Lazy([1, 2, 3, 4]).sum() Lazy([1.2, 3.4]).sum(Math.floor) Lazy(['foo', 'bar']).sum('length')takeWhile Sequence#takeWhile
Creates a new sequence comprising the elements from the head of this sequence that satisfy some predicate. Once an element is encountered that doesn't satisfy the predicate, iteration will stop.
SignatureSequence.takeWhile = function(predicate) { }
Sequence.takeWhile = function takeWhile(predicate) { return new TakeWhileSequence(this, predicate); }Name Type(s) Description predicate Function returns Sequence
The new sequence
Examplesfunction lessThan(x) { return function(y) { return y < x; }; } Lazy([1, 2, 3, 4]).takeWhile(lessThan(3)) Lazy([1, 2, 3, 4]).takeWhile(lessThan(0))tap Sequence#tap
Passes each element in the sequence to the specified callback during iteration. This is like Sequence#each, except that it can be inserted anywhere in the middle of a chain of methods to "intercept" the values in the sequence at that point.
SignatureSequence.tap = function(callback) { }
Sequence.tap = function tap(callback) { return new TappedSequence(this, callback); }Name Type(s) Description callback Function
A function to call on every element in the sequence during iteration. The return value of this function does not matter.
returns SequenceA sequence comprising the same elements as this one.
ExamplesLazy([1, 2, 3]).tap(fn).each(Lazy.noop);toArray Sequence#toArray
Creates an array snapshot of a sequence.
Note that for indefinite sequences, this method may raise an exception or (worse) cause the environment to hang.
SignatureSequence.toArray = function() { }
Sequence.toArray = function toArray() { return this.reduce(function(arr, element) { arr.push(element); return arr; }, []); }Name Type(s) Description returns Array
An array containing the current contents of the sequence.
ExamplesLazy([1, 2, 3]).toArray()toObject Sequence#toObject
Creates an object from a sequence of key/value pairs.
SignatureSequence.toObject = function() { }
Sequence.toObject = function toObject() { return this.reduce(function(object, pair) { object[pair[0]] = pair[1]; return object; }, {}); }Name Type(s) Description returns Object
An object with keys and values corresponding to the pairs of elements in the sequence.
Examplesvar details = [ ["first", "Dan"], ["last", "Tao"], ["age", 29] ]; Lazy(details).toObject()union Sequence#union
Creates a new sequence with all the unique elements either in this sequence or among the specified arguments.
SignatureSequence.union = function(var_args) { }
Sequence.union = function union(var_args) { return this.concat(var_args).uniq(); }Name Type(s) Description var_args ...*
The values, or array(s) of values, to be additionally included in the resulting sequence.
returns SequenceThe new sequence.
ExamplesLazy(["foo", "bar"]).union([]) Lazy(["foo", "bar"]).union(["bar", "baz"])uniq Sequence#uniq
aliases: unique
Creates a new sequence with every unique element from this one appearing exactly once (i.e., with duplicates removed).
SignatureSequence.uniq = function(keyFn) { }
Sequence.uniq = function uniq(keyFn) { return new UniqueSequence(this, keyFn); }Name Type(s) Description keyFn Function?
An optional function to produce the key for each object. This key is then tested for uniqueness as opposed to the object reference.
returns SequenceThe new sequence.
ExamplesLazy([1, 2, 2, 3, 3, 3]).uniq() Lazy([{ name: 'mike' }, { name: 'sarah' }, { name: 'mike' } ]).uniq('name')Benchmarks
function randomOf(array) { return function() { return array[Math.floor(Math.random() * array.length)]; }; } var mostUnique = Lazy.generate(randomOf(_.range(100)), 100).toArray(), someUnique = Lazy.generate(randomOf(_.range(50)), 100).toArray(), mostDupes = Lazy.generate(randomOf(_.range(5)), 100).toArray(); Lazy(mostUnique).uniq().each(Lazy.noop) Lazy(someUnique).uniq().each(Lazy.noop) Lazy(mostDupes).uniq().each(Lazy.noop) _.each(_.uniq(mostUnique), _.noop) _.each(_.uniq(someUnique), _.noop) _.each(_.uniq(mostDupes), _.noop)Implementation mostly unique elements some unique elements mostly duplicate elements lazy lodash where Sequence#where
Creates a new sequence whose values are the elements of this sequence with property names and values matching those of the specified object.
SignatureSequence.where = function(properties) { }
Sequence.where = function where(properties) { return this.filter(properties); }Name Type(s) Description properties Object
The properties that should be found on every element that is to be included in this sequence.
returns SequenceThe new sequence.
Examplesvar people = [ { first: "Dan", last: "Tao" }, { first: "Bob", last: "Smith" } ]; Lazy(people).where({ first: "Dan" })Benchmarks
var animals = ["dog", "cat", "mouse", "horse", "pig", "snake"]; Lazy(animals).where({ length: 3 }).each(Lazy.noop) _.each(_.where(animals, { length: 3 }), _.noop)Implementation Ops/second lazy lodash without Sequence#without
aliases: difference
Creates a new sequence with all the elements of this sequence that are not also among the specified arguments.
SignatureSequence.without = function(var_args) { }
Sequence.without = function without(var_args) { return new WithoutSequence(this, arraySlice.call(arguments, 0)); }Name Type(s) Description var_args ...*
The values, or array(s) of values, to be excluded from the resulting sequence.
returns SequenceThe new sequence.
ExamplesLazy([1, 2, 3, 4, 5]).without(2, 3) Lazy([1, 2, 3, 4, 5]).without([4, 5])zip Sequence#zip
Creates a new sequence by combining the elements from this sequence with corresponding elements from the specified array(s).
SignatureSequence.zip = function(var_args) { }
Sequence.zip = function zip(var_args) { if (arguments.length === 1) { return new SimpleZippedSequence(this, ( var_args)); } else { return new ZippedSequence(this, arraySlice.call(arguments, 0)); } }Name Type(s) Description var_args ...Array
One or more arrays of elements to combine with those of this sequence.
returns SequenceThe new sequence.
ExamplesLazy([1, 2]).zip([3, 4]) Lazy([]).zip([0]) Lazy([0]).zip([]) Lazy([]).zip([1, 2], [3, 4]) Lazy([]).zip([1], [2, 3]) Lazy([1, 2]).zip([3], [4])Benchmarks
var smArrL = Lazy.range(10).toArray(), smArrR = Lazy.range(10, 20).toArray(), lgArrL = Lazy.range(100).toArray(), lgArrR = Lazy.range(100, 200).toArray(); Lazy(smArrL).zip(smArrR).each(Lazy.noop) Lazy(lgArrL).zip(lgArrR).each(Lazy.noop) _.each(_.zip(smArrL, smArrR), _.noop) _.each(_.zip(lgArrL, lgArrR), _.noop)Implementation zipping 10-element arrays zipping 100-element arrays lazy lodash ArrayLikeSequence ArrayLikeSequence
An ArrayLikeSequence
is a Sequence that provides random access to its elements. This extends the API for iterating with the additional methods #get and #length, allowing a sequence to act as a "view" into a collection or other indexed data source.
The initial sequence created by wrapping an array with Lazy(array)
is an ArrayLikeSequence
.
All methods of ArrayLikeSequence
that conceptually should return something like a array (with indexed access) return another ArrayLikeSequence
, for example:
The above is not an exhaustive list. There are also certain other cases where it might be possible to return an ArrayLikeSequence
(e.g., calling Sequence#concat with a single array argument), but this is not guaranteed by the API.
Note that in many cases, it is not possible to provide indexed access without first performing at least a partial iteration of the underlying sequence. In these cases an ArrayLikeSequence
will not be returned:
etc. The above methods only return ordinary Sequence objects.
Defining custom array-like sequencesCreating a custom ArrayLikeSequence
is essentially the same as creating a custom Sequence. You just have a couple more methods you need to implement: get
and (optionally) length
.
Here's an example. Let's define a sequence type called OffsetSequence
that offsets each of its parent's elements by a set distance, and circles back to the beginning after reaching the end. Remember: the initialization function you pass to #define should always accept a parent
as its first parameter.
ArrayLikeSequence.define("offset", {
init: function(parent, offset) {
this.offset = offset;
},
get: function(i) {
return this.parent.get((i + this.offset) % this.parent.length());
}
});
It's worth noting a couple of things here.
First, Lazy's default implementation of length
simply returns the parent's length. In this case, since an OffsetSequence
will always have the same number of elements as its parent, that implementation is fine; so we don't need to override it.
Second, the default implementation of each
uses get
and length
to essentially create a for
loop, which is fine here. If you want to implement each
your own way, you can do that; but in most cases (as here), you can probably just stick with the default.
So we're already done, after only implementing get
! Pretty easy, huh?
Now the offset
method will be chainable from any ArrayLikeSequence
. So for example:
Lazy([1, 2, 3]).map(mapFn).offset(3);
...will work, but:
Lazy([1, 2, 3]).filter(mapFn).offset(3);
...will not (because filter
does not return an ArrayLikeSequence
).
(Also, as with the example provided for defining custom Sequence types, this example really could have been implemented using a function already available as part of Lazy.js: in this case, Sequence#map.)
ExamplesLazy([1, 2, 3]) Lazy([1, 2, 3]).map(Lazy.identity) Lazy([1, 2, 3]).take(2) Lazy([1, 2, 3]).drop(2) Lazy([1, 2, 3]).reverse() Lazy([1, 2, 3]).slice(1, 2)define ArrayLikeSequence.define
Create a new constructor function for a type inheriting from ArrayLikeSequence
.
ArrayLikeSequence.define = function(methodName, overrides) { }
ArrayLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom array-like sequence must implement *at least* get!"); } return defineSequenceType(ArrayLikeSequence, methodName, overrides); }Name Type(s) Description methodName string|Array.<string>
The name(s) of the method(s) to be used for constructing the new sequence. The method will be attached to the ArrayLikeSequence
prototype so that it can be chained with any other methods that return array-like sequences.
An object containing function overrides for this new sequence type. Must include get
. May include init
, length
, getIterator
, and each
. For each function, this
will be the new sequence and this.parent
will be the source sequence.
A constructor for a new type inheriting from ArrayLikeSequence
.
Lazy.ArrayLikeSequence.define("offset", { init: function(offset) { this.offset = offset; }, get: function(i) { return this.parent.get((i + this.offset) % this.parent.length()); } }); Lazy([1, 2, 3]).offset(1)concat ArrayLikeSequence#concat
An optimized version of Sequence#concat that returns another ArrayLikeSequence if the argument is an array.
SignatureArrayLikeSequence.concat = function(var_args) { }
ArrayLikeSequence.concat = function concat(var_args) { if (arguments.length === 1 && isArray(arguments[0])) { return new IndexedConcatenatedSequence(this, ( var_args)); } else { return Sequence.prototype.concat.apply(this, arguments); } }Name Type(s) Description var_args ...* Examples
Lazy([1, 2]).concat([3, 4]) Lazy([1, 2]).concat([3, 4])first ArrayLikeSequence#first
An optimized version of Sequence#first, which creates an ArrayLikeSequence so that the result still provides random access.
ExamplesLazy([1, 2, 3]).first(2)get ArrayLikeSequence#get
Returns the element at the specified index.
SignatureArrayLikeSequence.get = function(i) { }
ArrayLikeSequence.get = function get(i) { return this.parent.get(i); }Name Type(s) Description i number
The index to access.
returns *The element.
Examplesfunction increment(x) { return x + 1; } Lazy([1, 2, 3]).get(1) Lazy([1, 2, 3]).get(-1) Lazy([1, 2, 3]).map(increment).get(1)length ArrayLikeSequence#length
Returns the length of the sequence.
SignatureArrayLikeSequence.length = function() { }
ArrayLikeSequence.length = function length() { return this.parent.length(); }Name Type(s) Description returns number
The length.
Examplesfunction increment(x) { return x + 1; } Lazy([]).length() Lazy([1, 2, 3]).length() Lazy([1, 2, 3]).map(increment).length()map ArrayLikeSequence#map
An optimized version of Sequence#map, which creates an ArrayLikeSequence so that the result still provides random access.
ExamplesLazy([1, 2, 3]).map(Lazy.identity)pop ArrayLikeSequence#pop
Returns a new sequence with the same elements as this one, minus the last element.
SignatureArrayLikeSequence.pop = function() { }
ArrayLikeSequence.pop = function pop() { return this.initial(); }Name Type(s) Description returns ArrayLikeSequence
The new array-like sequence.
ExamplesLazy([1, 2, 3]).pop() Lazy([]).pop()push ArrayLikeSequence#push
Returns a new sequence with the same elements as this one, plus the specified element at the end.
SignatureArrayLikeSequence.push = function() { }
ArrayLikeSequence.push = function push(value) { return this.concat([value]); }Name Type(s) Description returns ArrayLikeSequence
The new array-like sequence.
ExamplesLazy([1, 2]).push(3) Lazy([]).push(1)rest ArrayLikeSequence#rest
An optimized version of Sequence#rest, which creates an ArrayLikeSequence so that the result still provides random access.
ExamplesLazy([1, 2, 3]).rest()reverse ArrayLikeSequence#reverse
An optimized version of Sequence#reverse, which creates an ArrayLikeSequence so that the result still provides random access.
ExamplesLazy([1, 2, 3]).reverse()shift ArrayLikeSequence#shift
Returns a new sequence with the same elements as this one, minus the first element.
SignatureArrayLikeSequence.shift = function() { }
ArrayLikeSequence.shift = function shift() { return this.drop(); }Name Type(s) Description returns ArrayLikeSequence
The new array-like sequence.
ExamplesLazy([1, 2, 3]).shift() Lazy([]).shift()slice ArrayLikeSequence#slice
Returns a new sequence comprising the portion of this sequence starting from the specified starting index and continuing until the specified ending index or to the end of the sequence.
SignatureArrayLikeSequence.slice = function(begin, end) { }
ArrayLikeSequence.slice = function slice(begin, end) { var length = this.length(); if (begin < 0) { begin = length + begin; } var result = this.drop(begin); if (typeof end === "number") { if (end < 0) { end = length + end; } result = result.take(end - begin); } return result; }Name Type(s) Description begin number
The index at which the new sequence should start.
end number?The index at which the new sequence should end.
returns ArrayLikeSequenceThe new array-like sequence.
ExamplesLazy([1, 2, 3, 4, 5]).slice(0) Lazy([1, 2, 3, 4, 5]).slice(2) Lazy([1, 2, 3, 4, 5]).slice(2, 4) Lazy([1, 2, 3, 4, 5]).slice(-1) Lazy([1, 2, 3, 4, 5]).slice(1, -1) Lazy([1, 2, 3, 4, 5]).slice(0, 10)unshift ArrayLikeSequence#unshift
Returns a new sequence with the same elements as this one, plus the specified element at the beginning.
SignatureArrayLikeSequence.unshift = function() { }
ArrayLikeSequence.unshift = function unshift(value) { return Lazy([value]).concat(this); }Name Type(s) Description returns ArrayLikeSequence
The new array-like sequence.
ExamplesLazy([1, 2]).unshift(3) Lazy([]).unshift(1)ObjectLikeSequence ObjectLikeSequence
An ObjectLikeSequence
object represents a sequence of key/value pairs.
The initial sequence you get by wrapping an object with Lazy(object)
is an ObjectLikeSequence
.
All methods of ObjectLikeSequence
that conceptually should return something like an object return another ObjectLikeSequence
.
var obj = { foo: 'bar' }; Lazy(obj).assign({ bar: 'baz' }) Lazy(obj).defaults({ bar: 'baz' }) Lazy(obj).invert()define ObjectLikeSequence.define
Create a new constructor function for a type inheriting from ObjectLikeSequence
.
ObjectLikeSequence.define = function(methodName, overrides) { }
ObjectLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.each !== 'function') { throw new Error("A custom object-like sequence must implement *at least* each!"); } return defineSequenceType(ObjectLikeSequence, methodName, overrides); }Name Type(s) Description methodName string|Array.<string>
The name(s) of the method(s) to be used for constructing the new sequence. The method will be attached to the ObjectLikeSequence
prototype so that it can be chained with any other methods that return object-like sequences.
An object containing function overrides for this new sequence type. Must include each
. May include init
and get
(for looking up an element by key).
A constructor for a new type inheriting from ObjectLikeSequence
.
function downcaseKey(value, key) { return [key.toLowerCase(), value]; } Lazy.ObjectLikeSequence.define("caseInsensitive", { init: function() { var downcased = this.parent .map(downcaseKey) .toObject(); this.downcased = Lazy(downcased); }, get: function(key) { return this.downcased.get(key.toLowerCase()); }, each: function(fn) { return this.downcased.each(fn); } }); Lazy({ Foo: 'bar' }).caseInsensitive() Lazy({ FOO: 'bar' }).caseInsensitive().get('foo') Lazy({ FOO: 'bar' }).caseInsensitive().get('FOO')assign ObjectLikeSequence#assign
aliases: extend
Returns an ObjectLikeSequence whose elements are the combination of this sequence and another object. In the case of a key appearing in both this sequence and the given object, the other object's value will override the one in this sequence.
SignatureObjectLikeSequence.assign = function(other) { }
ObjectLikeSequence.assign = function assign(other) { return new AssignSequence(this, other); }Name Type(s) Description other Object
The other object to assign to this sequence.
returns ObjectLikeSequenceA new sequence comprising elements from this sequence plus the contents of other
.
Lazy({ "uno": 1, "dos": 2 }).assign({ "tres": 3 }) Lazy({ foo: "bar" }).assign({ foo: "baz" }); Lazy({ foo: 'foo' }).assign({ foo: false }).get('foo')async ObjectLikeSequence#async
Throws an exception. Asynchronous iteration over object-like sequences is not supported.
ExamplesLazy({ foo: 'bar' }).async()defaults ObjectLikeSequence#defaults
Returns an ObjectLikeSequence whose elements are the combination of this sequence and a 'default' object. In the case of a key appearing in both this sequence and the given object, this sequence's value will override the default object's.
SignatureObjectLikeSequence.defaults = function(defaults) { }
ObjectLikeSequence.defaults = function defaults(defaults) { return new DefaultsSequence(this, defaults); }Name Type(s) Description defaults Object
The 'default' object to use for missing keys in this sequence.
returns ObjectLikeSequenceA new sequence comprising elements from this sequence supplemented by the contents of defaults
.
Lazy({ name: "Dan" }).defaults({ name: "User", password: "passw0rd" }) Lazy({ foo: false }).defaults({ foo: 'foo' }).get('foo') Lazy({ a: 1 }).defaults({ b: 2 }).defaults({ c: 3 }) Lazy({ a: 1 }).defaults({ b: 2 }).defaults({ a: 3 }) Lazy({ a: 1, b: 2 }).defaults({ b: 5 }).defaults({ c: 3, d: 4 })functions ObjectLikeSequence#functions
aliases: methods
Creates a Sequence consisting of the keys from this sequence whose values are functions.
SignatureObjectLikeSequence.functions = function() { }
ObjectLikeSequence.functions = function functions() { return this .filter(function(v, k) { return typeof(v) === "function"; }) .map(function(v, k) { return k; }); }Name Type(s) Description returns Sequence
The new sequence.
Examplesvar dog = { name: "Fido", breed: "Golden Retriever", bark: function() { console.log("Woof!"); }, wagTail: function() { console.log("TODO: implement robotic dog interface"); } }; Lazy(dog).functions()get ObjectLikeSequence#get
Gets the element at the specified key in this sequence.
SignatureObjectLikeSequence.get = function(key) { }
ObjectLikeSequence.get = function get(key) { var pair = this.pairs().find(function(pair) { return pair[0] === key; }); return pair ? pair[1] : undefined; }Name Type(s) Description key string
The key.
returns *The element.
ExamplesLazy({ foo: "bar" }).get("foo") Lazy({ foo: "bar" }).extend({ foo: "baz" }).get("foo") Lazy({ foo: "bar" }).defaults({ bar: "baz" }).get("bar") Lazy({ foo: "bar" }).invert().get("bar") Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("foo") Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("bar") Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("bar") Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("foo")invert ObjectLikeSequence#invert
Returns an ObjectLikeSequence whose values are this sequence's keys, and whose keys are this sequence's values.
SignatureObjectLikeSequence.invert = function() { }
ObjectLikeSequence.invert = function invert() { return new InvertedSequence(this); }Name Type(s) Description returns ObjectLikeSequence
A new sequence comprising the inverted keys and values from this sequence.
ExamplesLazy({ first: "Dan", last: "Tao" }).invert()keys ObjectLikeSequence#keys
Returns a Sequence whose elements are the keys of this object-like sequence.
SignatureObjectLikeSequence.keys = function() { }
ObjectLikeSequence.keys = function keys() { return new KeySequence(this); }Name Type(s) Description returns Sequence
The sequence based on this sequence's keys.
Examplesvar obj = { hello: "hola", goodbye: "hasta luego" }; Lazy(obj).keys() Lazy(obj).keys().map(function(v, i) { return [v, i]; })merge ObjectLikeSequence#merge
Produces an ObjectLikeSequence consisting of all the recursively merged values from this and the given object(s) or sequence(s).
Note that by default this method only merges "vanilla" objects (bags of key/value pairs), not arrays or any other custom object types. To customize how merging works, you can provide the mergeFn argument, e.g. to handling merging arrays, strings, or other types of objects.
SignatureObjectLikeSequence.merge = function(others, mergeFn) { }
ObjectLikeSequence.merge = function merge(var_args) { var mergeFn = arguments.length > 1 && typeof arguments[arguments.length - 1] === "function" ? arrayPop.call(arguments) : null; return new MergedSequence(this, arraySlice.call(arguments, 0), mergeFn); }Name Type(s) Description others ...Object|ObjectLikeSequence
The other object(s) or sequence(s) whose values will be merged into this one.
mergeFn Function?An optional function used to customize merging behavior. The function should take two values as parameters and return whatever the "merged" form of those values is. If the function returns undefined then the new value will simply replace the old one in the final result.
returns ObjectLikeSequenceThe new sequence consisting of merged values.
Examplesvar names = { 'characters': [ { 'name': 'barney' }, { 'name': 'fred' } ] }; var ages = { 'characters': [ { 'age': 36 }, { 'age': 40 } ] }; var food = { 'fruits': ['apple'], 'vegetables': ['beet'] }; var otherFood = { 'fruits': ['banana'], 'vegetables': ['carrot'] }; function mergeArrays(a, b) { return Array.isArray(a) ? a.concat(b) : undefined; } Lazy(names).merge(ages); Lazy(food).merge(otherFood, mergeArrays); Lazy({ foo: 1 }).merge({ foo: 2 }); Lazy({ foo: 1 }).merge({ bar: 2 }); Lazy({ foo: { bar: 1 } }).merge({ foo: { bar: 2 } }); Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); Lazy({ foo: 1 }).merge({ bar: 2 }, { bar: 3 }); Lazy({ foo: 1 }).merge({ foo: undefined }); Lazy({ foo: 1 }).merge({ foo: null }); Lazy({ foo: [{ bar: 1 }] }).merge({ foo: [{ baz: 2 }] });omit ObjectLikeSequence#omit
Creates an ObjectLikeSequence consisting of the key/value pairs from this sequence excluding those with the specified keys. Non-string keys are effectively ignored.
SignatureObjectLikeSequence.omit = function(properties) { }
ObjectLikeSequence.omit = function omit(properties) { return new OmitSequence(this, properties); }Name Type(s) Description properties Array
An array of the properties to omit from this sequence.
returns ObjectLikeSequenceThe new sequence.
Examplesvar players = { "who": "first", "what": "second", "i don't know": "third" }; Lazy(players).omit(["who", "what"]) Lazy({1: 2, true: false}).omit([1, true])pairs ObjectLikeSequence#pairs
aliases: toArray
Maps the key/value pairs in this sequence to arrays.
SignatureObjectLikeSequence.pairs = function() { }
ObjectLikeSequence.pairs = function pairs() { return this.map(function(v, k) { return [k, v]; }); }Name Type(s) Description returns Sequence
An sequence of [key, value]
pairs.
var colorCodes = { red: "#f00", green: "#0f0", blue: "#00f" }; Lazy(colorCodes).pairs()pick ObjectLikeSequence#pick
Creates an ObjectLikeSequence consisting of the key/value pairs from this sequence whose keys are included in the given array of property names.
SignatureObjectLikeSequence.pick = function(properties) { }
ObjectLikeSequence.pick = function pick(properties) { return new PickSequence(this, properties); }Name Type(s) Description properties Array.<string>
An array of the properties to "pick" from this sequence.
returns ObjectLikeSequenceThe new sequence.
Examplesvar players = { "who": "first", "what": "second", "i don't know": "third" }; Lazy(players).pick(["who", "what"])toArray ObjectLikeSequence#toArray
Creates an array from the key/value pairs in this sequence.
SignatureObjectLikeSequence.toArray = function() { }
ObjectLikeSequence.toArray = function toArray() { return this.pairs().toArray(); }Name Type(s) Description returns Array
An array of [key, value]
elements.
var colorCodes = { red: "#f00", green: "#0f0", blue: "#00f" }; Lazy(colorCodes).toArray()toObject ObjectLikeSequence#toObject
Creates an object with the key/value pairs from this sequence.
SignatureObjectLikeSequence.toObject = function() { }
ObjectLikeSequence.toObject = function toObject() { return this.reduce(function(object, value, key) { object[key] = value; return object; }, {}); }Name Type(s) Description returns Object
An object with the same key/value pairs as this sequence.
Examplesvar colorCodes = { red: "#f00", green: "#0f0", blue: "#00f" }; Lazy(colorCodes).toObject()values ObjectLikeSequence#values
Returns a Sequence whose elements are the values of this object-like sequence.
SignatureObjectLikeSequence.values = function() { }
ObjectLikeSequence.values = function values() { return new ValuesSequence(this); }Name Type(s) Description returns Sequence
The sequence based on this sequence's values.
ExamplesLazy({ hello: "hola", goodbye: "hasta luego" }).values()watch ObjectLikeSequence#watch
Watches for all changes to a specified property (or properties) of an object and produces a sequence whose elements have the properties { property, value }
indicating which property changed and what it was changed to.
Note that this method only works on directly wrapped objects; it will not work on any arbitrary ObjectLikeSequence.
SignatureObjectLikeSequence.watch = function(propertyNames) { }
ObjectLikeSequence.watch = function watch(propertyNames) { throw new Error('You can only call #watch on a directly wrapped object.'); }Name Type(s) Description propertyNames string|Array?
A property name or array of property names to watch. If this parameter is undefined
, all of the object's current (enumerable) properties will be watched.
A sequence comprising { property, value }
objects describing each change to the specified property/properties.
var obj = {}, changes = []; Lazy(obj).watch('foo').each(function(change) { changes.push(change); }); obj.foo = 1; obj.bar = 2; obj.foo = 3; obj.foo; changes;StringLikeSequence StringLikeSequence
A StringLikeSequence
represents a sequence of characters.
The initial sequence you get by wrapping a string with Lazy(string)
is a StringLikeSequence
.
All methods of StringLikeSequence
that conceptually should return something like a string return another StringLikeSequence
.
function upcase(str) { return str.toUpperCase(); } Lazy('foo') Lazy('foo').toUpperCase() Lazy('foo').reverse() Lazy('foo').take(2) Lazy('foo').drop(1) Lazy('foo').substring(1) Lazy('foo').map(Lazy.identity) Lazy('foo').mapString(Lazy.identity)define StringLikeSequence.define
Create a new constructor function for a type inheriting from StringLikeSequence
.
StringLikeSequence.define = function(methodName, overrides) { }
StringLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom string-like sequence must implement *at least* get!"); } return defineSequenceType(StringLikeSequence, methodName, overrides); }Name Type(s) Description methodName string|Array.<string>
The name(s) of the method(s) to be used for constructing the new sequence. The method will be attached to the StringLikeSequence
prototype so that it can be chained with any other methods that return string-like sequences.
An object containing function overrides for this new sequence type. Has the same requirements as ArrayLikeSequence.define.
returns FunctionA constructor for a new type inheriting from StringLikeSequence
.
Lazy.StringLikeSequence.define("zomg", { length: function() { return this.parent.length() + "!!ZOMG!!!1".length; }, get: function(i) { if (i < this.parent.length()) { return this.parent.get(i); } return "!!ZOMG!!!1".charAt(i - this.parent.length()); } }); Lazy('foo').zomg()charAt StringLikeSequence#charAt
Returns the character at the given index of this sequence, or the empty string if the specified index lies outside the bounds of the sequence.
SignatureStringLikeSequence.charAt = function(i) { }
StringLikeSequence.charAt = function charAt(i) { return this.get(i); }Name Type(s) Description i number
The index of this sequence.
returns stringThe character at the specified index.
ExamplesLazy("foo").charAt(0) Lazy("foo").charAt(-1) Lazy("foo").charAt(10)charCodeAt StringLikeSequence#charCodeAt
Returns the character code at the given index of this sequence, or NaN
if the index lies outside the bounds of the sequence.
StringLikeSequence.charCodeAt = function(i) { }
StringLikeSequence.charCodeAt = function charCodeAt(i) { var char = this.charAt(i); if (!char) { return NaN; } return char.charCodeAt(0); }Name Type(s) Description i number
The index of the character whose character code you want.
returns numberThe character code.
ExamplesLazy("abc").charCodeAt(0) Lazy("abc").charCodeAt(-1) Lazy("abc").charCodeAt(10)contains StringLikeSequence#contains
Checks if this sequence contains a given substring.
SignatureStringLikeSequence.contains = function(substring) { }
StringLikeSequence.contains = function contains(substring) { return this.indexOf(substring) !== -1; }Name Type(s) Description substring string
The substring to check for.
returns booleanWhether or not this sequence contains substring
.
Lazy('hello').contains('ell') Lazy('hello').contains('') Lazy('hello').contains('abc')endsWith StringLikeSequence#endsWith
Checks if this sequence ends with a given suffix.
SignatureStringLikeSequence.endsWith = function(suffix) { }
StringLikeSequence.endsWith = function endsWith(suffix) { return this.substring(this.length() - suffix.length).toString() === suffix; }Name Type(s) Description suffix string
The suffix to check for.
returns booleanWhether or not this sequence ends with suffix
.
Lazy('foo').endsWith('oo') Lazy('foo').endsWith('') Lazy('foo').endsWith('abc')first StringLikeSequence#first
An optimized version of Sequence#first that returns another StringLikeSequence (or just the first character, if count
is undefined).
Lazy('foo').first() Lazy('fo').first(2) Lazy('foo').first(10) Lazy('foo').toUpperCase().first() Lazy('foo').toUpperCase().first(2)indexOf StringLikeSequence#indexOf
Finds the index of the first occurrence of the given substring within this sequence, starting from the specified index (or the beginning of the sequence).
SignatureStringLikeSequence.indexOf = function(substring, startIndex) { }
StringLikeSequence.indexOf = function indexOf(substring, startIndex) { return this.toString().indexOf(substring, startIndex); }Name Type(s) Description substring string
The substring to search for.
startIndex number?The index from which to start the search.
returns numberThe first index where the given substring is found, or -1 if it isn't in the sequence.
ExamplesLazy('canal').indexOf('a') Lazy('canal').indexOf('a', 2) Lazy('canal').indexOf('ana') Lazy('canal').indexOf('andy') Lazy('canal').indexOf('x')last StringLikeSequence#last
An optimized version of Sequence#last that returns another StringLikeSequence (or just the last character, if count
is undefined).
Lazy('foo').last() Lazy('foo').last(2) Lazy('foo').last(10) Lazy('foo').toUpperCase().last() Lazy('foo').toUpperCase().last(2)lastIndexOf StringLikeSequence#lastIndexOf
Finds the index of the last occurrence of the given substring within this sequence, starting from the specified index (or the end of the sequence) and working backwards.
SignatureStringLikeSequence.lastIndexOf = function(substring, startIndex) { }
StringLikeSequence.lastIndexOf = function lastIndexOf(substring, startIndex) { return this.toString().lastIndexOf(substring, startIndex); }Name Type(s) Description substring string
The substring to search for.
startIndex number?The index from which to start the search.
returns numberThe last index where the given substring is found, or -1 if it isn't in the sequence.
ExamplesLazy('canal').lastIndexOf('a') Lazy('canal').lastIndexOf('a', 2) Lazy('canal').lastIndexOf('ana') Lazy('canal').lastIndexOf('andy') Lazy('canal').lastIndexOf('x')mapString StringLikeSequence#mapString
Maps the characters of this sequence onto a new StringLikeSequence.
SignatureStringLikeSequence.mapString = function(mapFn) { }
StringLikeSequence.mapString = function mapString(mapFn) { return new MappedStringLikeSequence(this, mapFn); }Name Type(s) Description mapFn Function
The function used to map characters from this sequence onto the new sequence.
returns StringLikeSequenceThe new sequence.
Examplesfunction upcase(char) { return char.toUpperCase(); } Lazy("foo").mapString(upcase) Lazy("foo").mapString(upcase).charAt(0) Lazy("foo").mapString(upcase).charCodeAt(0) Lazy("foo").mapString(upcase).substring(1)match StringLikeSequence#match
Creates a Sequence comprising all of the matches for the specified pattern in the underlying string.
SignatureStringLikeSequence.match = function(pattern) { }
StringLikeSequence.match = function match(pattern) { return new StringMatchSequence(this, pattern); }Name Type(s) Description pattern RegExp
The pattern to match.
returns SequenceA sequence of all the matches.
ExamplesLazy("abracadabra").match(/a[bcd]/) Lazy("fee fi fo fum").match(/\w+/) Lazy("hello").match(/xyz/)reverse StringLikeSequence#reverse
Returns a copy of this sequence that reads back to front.
ExamplesLazy("abcdefg").reverse()split StringLikeSequence#split
Creates a Sequence comprising all of the substrings of this string separated by the given delimiter, which can be either a string or a regular expression.
SignatureStringLikeSequence.split = function(delimiter) { }
StringLikeSequence.split = function split(delimiter) { return new SplitStringSequence(this, delimiter); }Name Type(s) Description delimiter string|RegExp
The delimiter to use for recognizing substrings.
returns SequenceA sequence of all the substrings separated by the given delimiter.
ExamplesLazy("foo").split("") Lazy("yo dawg").split(" ") Lazy("bah bah\tblack sheep").split(/\s+/)startsWith StringLikeSequence#startsWith
Checks if this sequence starts with a given prefix.
SignatureStringLikeSequence.startsWith = function(prefix) { }
StringLikeSequence.startsWith = function startsWith(prefix) { return this.substring(0, prefix.length).toString() === prefix; }Name Type(s) Description prefix string
The prefix to check for.
returns booleanWhether or not this sequence starts with prefix
.
Lazy('foo').startsWith('fo') Lazy('foo').startsWith('') Lazy('foo').startsWith('abc')substring StringLikeSequence#substring
Returns a StringLikeSequence comprising the characters from this sequence starting at start
and ending at stop
(exclusive), or---if stop
is undefined
, including the rest of the sequence.
StringLikeSequence.substring = function(start, stop) { }
StringLikeSequence.substring = function substring(start, stop) { return new StringSegment(this, start, stop); }Name Type(s) Description start number
The index where this sequence should begin.
stop number?The index (exclusive) where this sequence should end.
returns StringLikeSequenceThe new sequence.
ExamplesLazy("foo").substring(1) Lazy("foo").substring(-1) Lazy("hello").substring(1, 3) Lazy("hello").substring(1, 9) Lazy("foo").substring(0, 0) Lazy("foo").substring(3, 3)toLowerCase StringLikeSequence#toLowerCase
Converts all of the characters in this string to lowercase.
SignatureStringLikeSequence.toLowerCase = function() { }
StringLikeSequence.toLowerCase = function toLowerCase() { return this.mapString(function(char) { return char.toLowerCase(); }); }Name Type(s) Description returns StringLikeSequence
A new sequence with the same characters as this sequence, all lowercase.
Examplesfunction nextLetter(a) { return String.fromCharCode(a.charCodeAt(0) + 1); } Lazy('FOO').toLowerCase() Lazy('FOO').substring(1).toLowerCase() Lazy('ABC').mapString(nextLetter).toLowerCase()toUpperCase StringLikeSequence#toUpperCase
Converts all of the characters in this string to uppercase.
SignatureStringLikeSequence.toUpperCase = function() { }
StringLikeSequence.toUpperCase = function toUpperCase() { return this.mapString(function(char) { return char.toUpperCase(); }); }Name Type(s) Description returns StringLikeSequence
A new sequence with the same characters as this sequence, all uppercase.
Examplesfunction nextLetter(a) { return String.fromCharCode(a.charCodeAt(0) + 1); } Lazy('foo').toUpperCase() Lazy('foo').substring(1).toUpperCase() Lazy('abc').mapString(nextLetter).toUpperCase()GeneratedSequence GeneratedSequence
A GeneratedSequence
does not wrap an in-memory collection but rather determines its elements on-the-fly during iteration according to a generator function.
You create a GeneratedSequence
by calling Lazy.generate.
function GeneratedSequence(generatorFn, length) { }
function GeneratedSequence(generatorFn, length) { this.get = generatorFn; this.fixedLength = length; }Name Type(s) Description generatorFn function(number):*
A function which accepts an index and returns a value for the element at that position in the sequence.
length number?The length of the sequence. If this argument is omitted, the sequence will go on forever.
each GeneratedSequence#eachIterates over the sequence produced by invoking this sequence's generator function up to its specified length, or, if length is undefined
, indefinitely (in which case the sequence will go on forever--you would need to call, e.g., Sequence#take to limit iteration).
GeneratedSequence.each = function(fn) { }
GeneratedSequence.each = function each(fn) { var generatorFn = this.get, length = this.fixedLength, i = 0; while (typeof length === "undefined" || i < length) { if (fn(generatorFn(i), i++) === false) { return false; } } return true; }Name Type(s) Description fn Function
The function to call on each output from the generator function.
length GeneratedSequence#lengthReturns the length of this sequence.
SignatureGeneratedSequence.length = function() { }
GeneratedSequence.length = function length() { return this.fixedLength; }Name Type(s) Description returns number
The length, or undefined
if this is an indefinite sequence.
An AsyncSequence
iterates over its elements asynchronously when #each is called.
You get an AsyncSequence
by calling Sequence#async on any sequence. Note that some sequence types may not support asynchronous iteration.
Because of its asynchronous nature, an AsyncSequence
cannot be used in the same way as other sequences for functions that return values directly (e.g., reduce
, max
, any
, even toArray
).
Instead, these methods return an AsyncHandle
whose onComplete
method accepts a callback that will be called with the final result once iteration has finished.
There are plenty of ways to define an asynchronous sequence. Here's one.
boolean
) and current (which returns the current value).AsyncSequence
, whose getIterator
function returns an instance of the iterator type you just defined.The default implementation for #each on an AsyncSequence
is to create an iterator and then asynchronously call Iterator#moveNext (using setImmediate
, if available, otherwise setTimeout
) until the iterator can't move ahead any more.
function AsyncSequence(parent, interval) { }
function AsyncSequence(parent, interval) { if (parent instanceof AsyncSequence) { throw new Error("Sequence is already asynchronous!"); } this.parent = parent; this.interval = interval; this.onNextCallback = getOnNextCallback(interval); this.cancelCallback = getCancelCallback(interval); }Name Type(s) Description parent Sequence
A Sequence to wrap, to expose asynchronous iteration.
interval number?How many milliseconds should elapse between each element when iterating over this sequence. Note that this interval applies even to the first value in the sequence; i.e., when calling each(), this much time will elapse before the first element is iterated.
If this argument is omitted, asynchronous iteration will be executed
as fast as possible.
contains AsyncSequence#contains
A version of Sequence#contains which returns an AsyncHandle.
SignatureAsyncSequence.contains = function(value) { }
AsyncSequence.contains = function contains(value) { var found = false; var handle = this.each(function(e) { if (e === value) { found = true; return false; } }); return handle.then(function() { return found; }); }Name Type(s) Description value *
The element to search for in the sequence.
returns AsyncHandleAn AsyncHandle (promise) which resolves to either true
or false
to indicate whether the element was found.
An asynchronous version of Sequence#each.
SignatureAsyncSequence.each = function(fn) { }
AsyncSequence.each = function each(fn) { var iterator = this.parent.getIterator(), onNextCallback = this.onNextCallback, cancelCallback = this.cancelCallback, i = 0; var handle = new AsyncHandle(function cancel() { if (cancellationId) { cancelCallback(cancellationId); } }); var cancellationId = onNextCallback(function iterate() { cancellationId = null; try { if (iterator.moveNext() && fn(iterator.current(), i++) !== false) { cancellationId = onNextCallback(iterate); } else { handle._resolve(); } } catch (e) { handle._reject(e); } }); return handle; }Name Type(s) Description fn Function
The function to invoke asynchronously on each element in the sequence one by one.
returns AsyncHandleAn AsyncHandle providing the ability to cancel the asynchronous iteration (by calling cancel()
) as well as supply callback(s) for when an error is encountered (onError
) or when iteration is complete (onComplete
).
A version of Sequence#find which returns an AsyncHandle.
SignatureAsyncSequence.find = function(predicate) { }
AsyncSequence.find = function find(predicate) { var found; var handle = this.each(function(e, i) { if (predicate(e, i)) { found = e; return false; } }); return handle.then(function() { return found; }); }Name Type(s) Description predicate Function
A function to call on (potentially) every element in the sequence.
returns AsyncHandleAn AsyncHandle (promise) which resolves to the found element, once it is detected, or else undefined
.
Throws an exception. You cannot manually iterate over an asynchronous sequence.
ExamplesLazy([1, 2, 3]).async().getIterator()indexOf AsyncSequence#indexOf
A version of Sequence#indexOf which returns an AsyncHandle.
SignatureAsyncSequence.indexOf = function(value) { }
AsyncSequence.indexOf = function indexOf(value) { var foundIndex = -1; var handle = this.each(function(e, i) { if (e === value) { foundIndex = i; return false; } }); return handle.then(function() { return foundIndex; }); }Name Type(s) Description value *
The element to search for in the sequence.
returns AsyncHandleAn AsyncHandle (promise) which resolves to the found index, once it is detected, or -1.
Iterator IteratorThe Iterator object provides an API for iterating over a sequence.
The purpose of the Iterator
type is mainly to offer an agnostic way of iterating over a sequence -- either synchronous (i.e. with a while
loop) or asynchronously (with recursive calls to either setTimeout
or --- if available --- setImmediate
). It is not intended to be used directly by application code.
function Iterator(sequence) { }
function Iterator(sequence) { this.sequence = sequence; this.index = -1; }Name Type(s) Description sequence Sequence
The sequence to iterate over.
current Iterator#currentGets the current item this iterator is pointing to.
SignatureIterator.current = function() { }
Iterator.current = function current() { return this.cachedIndex && this.cachedIndex.get(this.index); }Name Type(s) Description returns *
The current item.
moveNext Iterator#moveNextMoves the iterator to the next item in a sequence, if possible.
SignatureIterator.moveNext = function() { }
Iterator.moveNext = function moveNext() { var cachedIndex = this.cachedIndex; if (!cachedIndex) { cachedIndex = this.cachedIndex = this.sequence.getIndex(); } if (this.index >= cachedIndex.length() - 1) { return false; } ++this.index; return true; }Name Type(s) Description returns boolean
True if the iterator is able to move to a new item, or else false.
AsyncHandle AsyncHandleAn AsyncHandle
provides a Promises/A+ compliant interface for an AsyncSequence that is currently (or was) iterating over its elements.
In addition to behaving as a promise, an AsyncHandle
provides the ability to AsyncHandle#cancel iteration (if cancelFn
is provided) and also offers convenient AsyncHandle#onComplete and AsyncHandle#onError methods to attach listeners for when iteration is complete or an error is thrown during iteration.
function AsyncHandle(cancelFn) { }
function AsyncHandle(cancelFn) { this.resolveListeners = []; this.rejectListeners = []; this.state = PENDING; this.cancelFn = cancelFn; }Name Type(s) Description cancelFn Function
A function to cancel asynchronous iteration. This is passed in to support different cancellation mechanisms for different forms of asynchronous sequences (e.g., timeout-based sequences, sequences based on I/O, etc.).
Examplesvar sequence = Lazy.generate(Math.random) .chunk(100) .async() .take(1000); var handle = sequence.toArray(); handle.onComplete(function(array) { }); var flattened = handle.then(function(array) { return Lazy(array).flatten(); });cancel AsyncHandle#cancel
Cancels asynchronous iteration.
onComplete AsyncHandle#onCompleteUpdates the handle with a callback to execute when iteration is completed.
SignatureAsyncHandle.onComplete = function(callback) { }
AsyncHandle.onComplete = function onComplete(callback) { this.resolveListeners.push(callback); return this; }Name Type(s) Description callback Function
The function to call when the asynchronous iteration is completed.
onError AsyncHandle#onErrorUpdates the handle with a callback to execute if/when any error is encountered during asynchronous iteration.
SignatureAsyncHandle.onError = function(callback) { }
AsyncHandle.onError = function onError(callback) { this.rejectListeners.push(callback); return this; }Name Type(s) Description callback Function
The function to call, with any associated error object, when an error occurs.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4