8000 Add zip and zipWith · powercoder23/immutable-js@16a6e49 · GitHub
[go: up one dir, main page]

Skip to content

Commit 16a6e49

Browse files
committed
Add zip and zipWith
As suggested by immutable-js#51, and similar to those methods found in haskell and scala
1 parent 5f135a7 commit 16a6e49

File tree

8 files changed

+321
-31
lines changed

8 files changed

+321
-31
lines changed

Gruntfile.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,15 @@ module.exports = function(grunt) {
8585

8686
var transformResult = require("es6-transpiler").run({
8787
src: bundled,
88+
disallowUnknownReferences: false,
8889
environments: ["node", "browser"],
8990
globals: {
9091
define: false,
9192
},
9293
});
9394

9495
if (transformResult.errors && transformResult.errors.length > 0) {
95-
throw transformResult.errors[0];
96+
throw new Error(transformResult.errors[0]);
9697
}
9798

9899
var transformed = transformResult.src;

__tests__/zip.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
///<reference path='../resources/jest.d.ts'/>
2+
///<reference path='../dist/immutable.d.ts'/>
3+
4+
jest.autoMockOff();
5+
6+
import I = require('immutable');
7+
8+
import jasmineCheck = require('jasmine-check');
9+
jasmineCheck.install();
10+
11+
describe('zip', () => {
12+
13+
it('zips lists into a list of tuples', () => {
14+
expect(
15+
I.Seq.of(1,2,3).zip(I.Seq.of(4,5,6)).toArray()
16+
).toEqual(
17+
[[1,4],[2,5],[3,6]]
18+
);
19+
});
20+
21+
it('zips with infinite lists', () => {
22+
expect(
23+
I.Range().zip(I.Seq.of('A','B','C')).toArray()
24+
).toEqual(
25+
[[0,'A'],[1,'B'],[2,'C']]
26+
);
27+
});
28+
29+
it('has unknown size when zipped with unknown size', () => {
30+
var seq = I.Range(0, 10);
31+
var zipped = seq.zip(seq.filter(n => n % 2 === 0));
32+
expect(zipped.size).toBe(undefined);
33+
expect(zipped.count()).toBe(5);
34+
})
35+
36+
check.it('is always the size of the smaller sequence',
37+
[gen.notEmpty(gen.array(gen.posInt))], (lengths) => {
38+
var ranges = lengths.map(l => I.Range(0, l));
39+
var first = ranges.shift();
40+
var zipped = first.zip.apply(first, ranges);
41+
var shortestLength = Math.min.apply(Math, lengths);
42+
expect(zipped.size).toBe(shortestLength);
43+
});
44+
45+
describe('zipWith', () => {
46+
47+
it('zips with a custom function', () => {
48+
expect(
49+
I.Seq.of(1,2,3).zipWith<number, number>(
50+
(a, b) => a + b,
51+
I.Seq.of(4,5,6)
52+
).toArray()
53+
).toEqual(
54+
[5,7,9]
55+
);
56+
});
57+
58+
it('can zip to create immutable collections', () => {
59+
expect(
60+
I.Seq.of(1,2,3).zipWith(
61+
() => I.List(arguments),
62+
I.Seq.of(4,5,6),
63+
I.Seq.of(7,8,9)
64+
).toJS()
65+
).toEqual(
66+
[[1,4,7],[2,5,8],[3,6,9]]
67+
);
68+
});
69+
70+
});
71+
72+
});

dist/immutable.d.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,44 @@ declare module 'immutable' {
22092209
...values: /*Array<IndexedIterable<T> | T>*/any[]
22102210
): /*this*/IndexedIterable<T>;
22112211

2212+
/**
2213+
* Returns an Iterable of the same type "zipped" with the provided
2214+
* iterables.
2215+
*
2216+
* Like `zipWith`, but using the default `zipper`: creating an `Array`.
2217+
*
2218+
* var a = Seq.of(1, 2, 3);
2219+
* var b = Seq.of(4, 5, 6);
2220+
* var c = a.zip(b); // Seq [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
2221+
*
2222+
*/
2223+
zip(...iterables: /*Array<IndexedIterable<T>>*/Array<any>): /*this*/IndexedIterable<any>;
2224+
2225+
/**
2226+
* Returns an Iterable of the same type "zipped" with the provided
2227+
* iterables by using a custom `zipper` function.
2228+
*
2229+
* Like `zipWith`, but using the default `zipper`: creating an `Array`.
2230+
*
2231+
* var a = Seq.of(1, 2, 3);
2232+
* var b = Seq.of(4, 5, 6);
2233+
* var c = a.zip(b); // Seq [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
2234+
*
2235+
*/
2236+
zipWith<U, Z>(
2237+
zipper: (value: T, otherValue: U) => Z,
2238+
otherIterable: IndexedIterable<U>
2239+
): IndexedIterable<Z>;
2240+
zipWith<U, V, Z>(
2241+
zipper: (value: T, otherValue: U, thirdValue: V) => Z,
2242+
otherIterable: IndexedIterable<U>,
2243+
thirdIterable: IndexedIterable<V>
2244+
): IndexedIterable<Z>;
2245+
zipWith<Z>(
2246+
zipper: (...any: Array<any>) => Z,
2247+
...iterables: /*Array<IndexedIterable<T>>*/Array<any>
2248+
): IndexedIterable<Z>;
2249+
22122250

22132251
// Search for value
22142252

dist/immutable.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,61 @@
16091609
}
16101610

16111611

1612+
function zipWithFactory(keyIter, zipper, iters) {
1613+
var zipSequence = makeSequence(keyIter);
1614+
zipSequence.size = new ArraySeq(iters).map(function(i ) {return i.size}).min();
1615+
// Note: this a generic base implementation of __iterate in terms of
1616+
// __iterator which may be more generically useful in the future.
1617+
zipSequence.__iterate = function(fn, reverse) {
1618+
/* generic:
1619+
var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
1620+
var step;
1621+
var iterations = 0;
1622+
while (!(step = iterator.next()).done) {
1623+
iterations++;
1624+
if (fn(step.value[1], step.value[0], this) === false) {
1625+
break;
1626+
}
1627+
}
1628+
return iterations;
1629+
*/
1630+
// indexed:
1631+
var iterator = this.__iterator(ITERATE_VALUES, reverse);
1632+
var step;
1633+
var iterations = 0;
1634+
while (!(step = iterator.next()).done) {
1635+
if (fn(step.value, iterations++, this) === false) {
1636+
break;
1637+
}
1638+
}
1639+
return iterations;
1640+
};
1641+
zipSequence.__iteratorUncached = function(type, reverse) {
1642+
var iterators = iters.map(function(i )
1643+
{return (i = Iterable(i), getIterator(reverse ? i.reverse() : i))}
1644+
);
1645+
var iterations = 0;
1646+
var isDone = false;
1647+
return new Iterator(function() {
1648+
var steps;
1649+
if (!isDone) {
1650+
steps = iterators.map(function(i ) {return i.next()});
1651+
isDone = steps.some(function(s ) {return s.done});
1652+
}
1653+
if (isDone) {
1654+
return iteratorDone();
1655+
}
1656+
return iteratorValue(
1657+
type,
1658+
iterations++,
1659+
zipper.apply(null, steps.map(function(s ) {return s.value}))
1660+
);
1661+
});
1662+
};
1663+
return zipSequence
1664+
}
1665+
1666+
16121667
// #pragma Helper Functions
16131668

16141669
function reify(iter, seq) {
@@ -4646,6 +4701,17 @@
46464701
return reify(this, skipWhileFactory(this, predicate, context, false));
46474702
},
46484703

4704+
zip: function(/*, ...iterables */) {
4705+
var iterables = [this].concat(arrCopy(arguments));
4706+
return reify(this, zipWithFactory(this, defaultZipper, iterables));
4707+
},
4708+
4709+
zipWith: function(zipper/*, ...iterables */) {
4710+
var iterables = arrCopy(arguments);
4711+
iterables[0] = this;
4712+
return reify(this, zipWithFactory(this, zipper, iterables));
4713+
},
4714+
46494715
});
46504716

46514717
IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true;
@@ -4714,6 +4780,10 @@
47144780
return typeof value === 'string' ? JSON.stringify(value) : value;
47154781
}
47164782

4783+
function defaultZipper() {
4784+
return arrCopy(arguments);
4785+
}
4786+
47174787
function defaultNegComparator(a, b) {
47184788
return a < b ? 1 : a > b ? -1 : 0;
47194789
}

0 commit comments

Comments
 (0)
0