@@ -19,12 +19,12 @@ const assert = require('assert');
19
19
const { inspect } = require ( 'util' ) ;
20
20
const { curry, pipe } = require ( './functional' ) ;
21
21
const {
22
- plus, or, mul, and,
22
+ plus, or, mul, and, is ,
23
23
} = require ( './op' ) ;
24
24
const { type } = require ( './typesafe' ) ;
25
25
const { Trait } = require ( './trait' ) ;
26
26
const {
27
- size, Size, pairs, eq, empty, _typedArrays,
27
+ size, Size, pairs, eq, empty, _typedArrays, setdefault ,
28
28
} = require ( './stdtraits' ) ;
29
29
30
30
// ITERATOR GENERATORS ///////////////////////////////////////
@@ -1249,6 +1249,18 @@ const takeWhile = curry('takeWhile', function* takeWhile(seq, fn) {
1249
1249
}
1250
1250
} ) ;
1251
1251
1252
+ /**
1253
+ * Cut off the sequence at the first point where the given condition is met.
1254
+ *
1255
+ * `list(takeUntil([1,2,3,4,5,6...], x => x > 4))` yields `[1,2,3,4]`
1256
+ *
1257
+ * @function
1258
+ * @param {Sequence } seq Any sequence for which iter() is defined
1259
+ * @param {Function } fn The predicate function
1260
+ * @returns {Iterator }
1261
+ */
1262
+ const takeUntil = curry ( 'takeUntil' , ( seq , fn ) => takeWhile ( seq , ( v ) => ! fn ( v ) ) ) ;
1263
+
1252
1264
/**
1253
1265
* Cut of the sequence at the point where the given value is
1254
1266
* first encountered.
@@ -1257,7 +1269,7 @@ const takeWhile = curry('takeWhile', function* takeWhile(seq, fn) {
1257
1269
* @param {Sequence } seq Any sequence for which iter() is defined
1258
1270
* @returns {Iterator }
1259
1271
*/
1260
- const takeUntilVal = curry ( 'takeUntilVal' , ( seq , val ) => takeWhile ( seq , ( x ) => x !== val ) ) ;
1272
+ const takeUntilVal = curry ( 'takeUntilVal' , ( seq , val ) => takeUntil ( seq , is ( val ) ) ) ;
1261
1273
1262
1274
/**
1263
1275
* Cut of the given sequence at the first undefined or null value.
@@ -1659,6 +1671,64 @@ const chunkifyWithFallback = curry('chunkifyWithFallback', (seq, len, fallback)
1659
1671
} ) ,
1660
1672
) ) ;
1661
1673
1674
+ /**
1675
+ * Group the elements of the user defined sequence using a custom container.
1676
+ *
1677
+ * This will:
1678
+ *
1679
+ * - Calculate the key for every element in the given sequence by
1680
+ * applying the key function
1681
+ * - Create a bucket (array) for every key calculated
1682
+ * - Insert each element into the bucket associated with
1683
+ * it's calculated key in order
1684
+ *
1685
+ * ```js,test
1686
+ * const { group, assertEquals } = require('ferrum');
1687
+ *
1688
+ * const seq = [
1689
+ * { foo: 42, bar: 22 },
1690
+ * { foo: 13, bar: 22 },
1691
+ * { foo: 42, bar: 99 },
1692
+ * ];
1693
+ *
1694
+ * // Group by `foo`
1695
+ * assertEquals(
1696
+ * group(seq, ({foo}) => foo),
1697
+ * new Map([
1698
+ * [42, [
1699
+ * { foo: 42, bar: 22 }, // Note that the order in here is well defined
1700
+ * { foo: 42, bar: 99 }]],
1701
+ * [13, [
1702
+ * { foo: 13, bar: 22 }]]
1703
+ * ])
1704
+ * );
1705
+ *
1706
+ * // Group by `bar`
1707
+ * assertEquals(
1708
+ * group(seq, ({bar}) => bar),
1709
+ * new Map([
1710
+ * [22, [
1711
+ * { foo: 42, bar: 22 },
1712
+ * { foo: 13, bar: 22 }]],
1713
+ * [42, [
1714
+ * { foo: 42, bar: 99 }]]
1715
+ * ])
1716
+ * );
1717
+ * ```
1718
+ *
1719
+ * @function
1720
+ * @sourcecode
1721
+ * @param {Sequence } seq
1722
+ * @param {Function } keyfn
1723
+ * @returns {Map } The es6 map containing the keys.
1724
+ */
1725
+ const group = curry ( 'group' , ( seq , keyfn ) => {
1726
+ const cont = new Map ( ) ;
1727
+ each ( seq , ( elm ) => setdefault ( cont , keyfn ( elm ) , [ ] ) . push ( elm ) ) ;
1728
+ return cont ;
1729
+ } ) ;
1730
+
1731
+
1662
1732
/**
1663
1733
* Calculate the cartesian product of the given sequences.
1664
1734
*
@@ -1831,6 +1901,7 @@ module.exports = {
1831
1901
take,
1832
1902
takeWithFallback,
1833
1903
takeWhile,
1904
+ takeUntil,
1834
1905
takeUntilVal,
1835
1906
takeDef,
1836
1907
flat,
@@ -1851,6 +1922,7 @@ module.exports = {
1851
1922
chunkifyShort,
1852
1923
chunkify,
1853
1924
chunkifyWithFallback,
1925
+ group,
1854
1926
cartesian,
1855
1927
cartesian2,
1856
1928
mod,
0 commit comments