npm install gf-js --save
Write some extensions function for GeneratorFunction and Array. We expand and attach most of lodash
functions to Array
and GeneratorFunction
by applying technique Extension Methods
or Extension Function
in Javascript
.
Eg:
The normal using
const _ = require('lodash');
const GF = require('gf-js');
let x = [1,2,3,4,5]
// lodash function
_.chunk(x,2); //[ [1, 2], [3, 4], [5]]
// Using chain function
_(x).chunk(2)
.toValues();
// Our module can attach function to `Array` class
x.chunk(2); // [[1, 2], [3, 4], [5]]
// Our module can chunk by an
// array of size (not only one fixed size)
x.chunk([2,3]); // [[1,2], [3,4,5]]
We can chunk the infinite-loop Generator
//infinite-loop `Generator`
function *number(){
for(let i = 0; ;i++) yield i;
}
//chunker
let chunker = number().ichunk(2);
for(let v in chunker){
console.log(v);
// [0, 1]
// [2, 3]
// [4, 5]
// ...
// ...
// loop infinite - please press `Ctrl-B` to break
}
GeneratorFunction
is Function
can return a Generator
object. . Instead of saving all entrie data as an Array
, the Generator
generates the next value as needed base on the previous value. So that the Generator
does not waste memory, and it can be generator infinite values. You can read more information in function*
Eg:
The normal GeneratorFunction
generates 2 values
//The normal `GeneratorFunction` generates 2 values
function* generator(i) {
yield i;
yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value);
// expected output: 10
console.log(gen.next().value);
// expected output: 20
The infinite-loop GeneratorFunction
generates all positive numbers
//The infinite-loop `GeneratorFunction` generates all positive numbers
function *number(){
for(let i = 0; ;i++) yield i;
}
//This code prints unfinite number in the screen.
//You must be break it by `Ctrl+B`
for(let item of number()){
console.log(item);
}
Open sample folder to see a lot of tutorials
Before using, you have to import it in your project first
const GF = require('gf-js')
After that all functions is pluged-in to Array
and Generator
and you can use it any where.
All APIs are add-on to JavaScript Array
and GeneratorFunction
extension functions.
Note: Because the
Javascript
language architecture is not good asC#
orPython
, theArray
class does not inherit fromGenerator
, we must deploy the functions for both and write the functions to convert between them. Almost functions start withi
return aGenerator
, and withouti
return anArray
Convert GeneratorFunction
(GF) instance to Array
instance
Eg:
function* generator(i) {
yield i;
yield i + 10;
}
let g = generator(5);
let arr = g.toArray(); //arr = [0,1,2,3,4,5]
Convert Array
instance to Generator
let g = [1,2,3,4,5].toGenerator()
now g
equal to
function* generator() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}
g = generator()
Sum all elements in this Array or GF
console.log([1,2,3].sum()) //1+2+3 = 6
Count the number of element
console.log([1,2,3].count()) //3
Average of all elements in this array or GF
console.log([1,2,3].avg()) // (1+2+3)/ 3 = 2
Implement Array.prototype.forEach(callback)
for GF
Create a new array with the results of calling a provided function on every element in the calling array. Same as Array.prototype.map(callback)
.
The callback
parameter is GetCallBack
/**
* @typedef {String|Function|Array<string>} GetCallback
*/
It can be a function
function *generator(n){
for (let i =0 ; i < n; i++) yield i;
}
let g = generator(10);
let h = g.imapBy(i=>i*2).toArray(); //[0,2,4,6,8,10,12,14,16,18]
let k = g.mapBy(i=>i*3); //[0,3,6,9,12,15,18,21,24,27]
Or string
if the values of Array
or Generator
are key-value pair object
const users = [
{ user: 'barney', age: 36, active: true, heigh: 10 },
{ user: 'barney', age: 36, active: true, heigh: 12 },
{ user: 'fred', age: 40, active: false, heigh: 11 },
{ user: 'barney', age: 40, active: true, heigh: 12 }
];
const usernames = users.mapBy('user');
// ['ronaldo','barney','fred','barney']
Or Array<string>
const shortUsers = users.mapBy(['user','active'])
// [
// { user: 'barney', active: true },
// { user: 'barney', active: true },
// { user: 'fred', active: false },
// { user: 'barney', active: true }
// ]
See map.spl.js for more samples.
The same python build-in zip
function
let x = [1,2,3,4];
let y = ['a','b','c','d'];
let z = Array.zip(x,y);
//z = [[1,'a'],[2,'b'],[3,'c'],[4,'d']]
The same python build-in zip
function but returns Generator
instead of Array
let x = [1,2,3,4];
let y = ['a','b','c','d'];
let z = Array.izip(x,y);
for(let [a,b] of z){
console.log(a,b)
}
the display is
1 a
2 b
3 c
4 d
The same python itertools.chain
function.
let x = [1,2,3,4];
let y = ['a','b','c','d'];
let z = Array.ichain(x,y);
for(let e of z){
console.log(e)
}
the display is
1
2
3
4
a
b
c
d
The same python itertools.chain
function but returns Array instead of GF.
let x = [1,2,3,4];
let y = ['a','b','c','d'];
let z = Array.chain(x,y);
//z = [1,2,3,4,'a','b','c','d']
See chunk-chain.spl.js to see more samples.
Creates an array of elements split into groups the length of size. If array can't be split evenly, the final chunk will be the remaining elements. Implememt lodash chunk
. But the size
parameter is more flexible
The size
parameter can be a number
let x = [1,2,3,4,5,6,7];
let y = x.chunk(2);
// y = [[1,2],[3,4],[5,6],[7]]
function* generator(n) {
for(let i = 0; i < n; i++) yield i;
}
let g = generator(7);
let h = g.chunk(2);
// h = [[0,1],[2,3],[4,5],[6]]
Or can be an array of numbers
let y = x.chunk([2,3,4])
// y = [
// [1, 2],
// [3,4,5],
// [6,7] // not enough 4 elements because x is too short
// ]
Or can be a Generator
function *size(){
yield 2;
yield 3;
yield 4;
}
let y = x.chunk(size())
// y = [
// [1, 2],
// [3,4,5],
// [6,7] // not enough 4 elements because x is too short
// ]
An infinite-loop Generator
let x = [1,2,3,4,5,6,7,8,9,10, 11]
let y = x.chunk([2,3].repepat()) //loop 2, 3 infinite
// y = [
// [1, 2], //2
// [3,4,5], //3
// [6,7], //2
// [8, 9, 10], //3
// [11] // remain only one item
// ]
See chunk-chain.spl.js to see more samples.
Same Array.prototype.filter(callback)
. A callback
not only a function, but also a DecisionCallback
.
/**
* A string, a function or a object<key,value> object.
* @typedef {String|Function|Object.<string,string>} DecisionCallback
*/
callback
is function
function* generator(n) {
for(let i = 0; i < n; i++) yield i;
}
let g = generator(7);
let h = g.filterBy(x=>x%3==0);
// h = [0,3,6]
const users = [
{ user: 'barney', age: 36, active: true, heigh: 10 },
{ user: 'barney', age: 36, active: true, heigh: 12 },
{ user: 'fred', age: 40, active: false, heigh: 11 },
{ user: 'barney', age: 40, active: true, heigh: 12 }
]
users.filterBy(({active})=>active);
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'barney', age: 36, active: true, heigh: 12 },
// ]
callback
is string
users.filterBy(`active`);
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'barney', age: 36, active: true, heigh: 12 },
// ]
callback
is object
users.filterBy({heigh:12});
// [
// { user: 'barney', age: 36, active: true, heigh: 12 },
// { user: 'barney', age: 40, active: true, heigh: 12 }
// ]
users.filterBy({heigh:12, age:36});
// [
// { user: 'barney', age: 36, active: true, heigh: 12 },
// ]
See filter.spl.js for more samples.
Same python build-in range function.
We can user function in two types:
range
(stop)
range
(start, stop[, step])
let x = Array.range(5); //x = [0,1,2,3,4]
let y = Array.range(1,11); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let z = Array.range(0, -10, -1); //[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
Group all items with the same key in the same group.
The callback
parameter is GetCallback
. See mapBy
method.
let x = range(10); //x=[0,1,2,3,4,5,6,7,8,9]
let g = x.groupBy(x=>x%2);
//g = {
// '0':[0,2,4,6,8],
// '1':[1,3,5,7,9]
// }
const users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 36, 'active': false },
{ 'user': 'mary', 'age': 40, 'active': true },
{ 'user': 'lazzy', 'age': 40, 'active': false },
];
users.groupBy('age');
// {
// '36': [
// { user: 'barney', age: 36, active: true },
// { user: 'fred', age: 36, active: false }
// ],
// '40': [
// { user: 'mary', age: 40, active: true },
// { user: 'lazzy', age: 40, active: false }
// ]
// }
See group-partition-count-distinct.spl.js for more samples.
The same as groupBy
function but instead of return array of items, just return the number of item in the same group.
const users = [
{ 'user': 'barney', 'age': 36, 'active': true },
{ 'user': 'fred', 'age': 36, 'active': false },
{ 'user': 'mary', 'age': 40, 'active': true },
{ 'user': 'lazzy', 'age': 40, 'active': false },
];
users.countBy('age');
//{ '36': 2, '40': 2 }
See group-partition-count-distinct.spl.js for more samples.
The same as groupBy
but not return the keys, only array of values.
See group-partition-count-distinct.spl for more samples.
Filter the difference items in this Array. The callback
parameter is GetCallback
. See mapBy
method.
let x = [1,2,3,4,5,6,5,7,6,8];
let d1 = x.distinct(); //d1 = [1,2,3,4,5,6,7,8]
let d2 = x.distinct(x=>x%5); //d2 = [1,2,3,4,5];
See group-partition-count-distinct.spl for more samples.
Get the min, max by callback
. The callback
parameter is GetCallback
. Instead of Math.min
and Math.max
functions, the return value is the original value, not the value after apply callback
. If includeIndex
is true
return pair of value and index of value
x = [1, 2, 3, 4, 5, 4]
console.log(x.min(), x.max())
y = [
[1, 3, -4],
[0],
[-0],
[1, 2],
[1, 3],
[1, 3, -5],
[0, 5]
]
console.log(y.min(includeIndex = true))
console.log(y.max(includeIndex = false))
console.log(y.minBy(v => v[1]))
console.log(y.minBy(v => v[1]))
var users = [
{ 'user': 'barney', 'age': 36, 'active': true, 'heigh': 10 },
{ 'user': 'barney', 'age': 36, 'active': true, 'heigh': 12 },
{ 'user': 'fred', 'age': 40, 'active': false, 'heigh': 11 },
{ 'user': 'barney', 'age': 40, 'active': true, 'heigh': 12 },
];
See min-max.spl.js for more samples.
Special functions of minBy
and maxBy
. Not apply callback
for item.
Insead of returning value, the function return the index of value in GF
or Array
. See min-max.spl.js
console.log(users.argMinBy('age'), users.minBy('age'));
console.log(users.argMaxBy('age'), users.maxBy('age'));
console.log(users.minBy('age', includeIndex = true));
console.log(users.maxBy('age', includeIndex = true));
console.log(users.minBy(['age', 'heigh']));
console.log(users.maxBy(['age', 'heigh']));
Special functions of argMinBy
and argMaxBy
. Not apply callback
for item.
Order the item by callback
same as Array.prototype.sort(). The callback
is not a comparator function, it is GetCallback
, and we use <
, >
, ==
for compare. We write compare to compare 2 array by dictionary compare.
const users = [
{ user: 'barney', age: 36, active: true, heigh: 10 },
{ user: 'barney', age: 46, active: true, heigh: 12 },
{ user: 'fred', age: 40, active: false, heigh: 11 },
{ user: 'barney', age: 40, active: true, heigh: 12 }
];
//order by `age`
users.orderBy('age');
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'fred', age: 40, active: false, heigh: 11 },
// { user: 'barney', age: 40, active: true, heigh: 12 },
// { user: 'barney', age: 46, active: true, heigh: 12 }
// ]
//order by `heigh`, if order by `age`
users.orderBy(['heigh','age']);
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'fred', age: 40, active: false, heigh: 11 },
// { user: 'barney', age: 40, active: true, heigh: 12 },
// { user: 'barney', age: 46, active: true, heigh: 12 }
// ]
See orderby.spl.js for more samples.
Apply Array.prototype.some(callback)
to GF.
function *generator(){
yield 1;
yield 2;
yield 5;
yield 7;
};
let g = generator();
let has5 = g.someBy(x=>x == 5); //true
let has7 = g.someBy(x=>x == 7); //true
let has6 = g.someBy(x=>x == 6); //false
Apply Array.prototype.every(callback)
to GF.
function *generator(){
yield 2;
yield 4;
yield 6;
yield 8;
};
let g = generator();
let even = g.everyBy(x=>x%2==0); //true
let mod3 = g.someBy(x=>x%3==0); //false
Repeats all items in this number
of times. If the number
is undefined
, repeat infinite.
Eg:
for(let item of [1,2].repeat(5)){
console.log(item);
}
//infinite loop
for(let item of [1,2].repeat()){
console.log(item);
}
Same as Array.prototype.slice(begin, [end])
. See skip-take.spl.js
Equal to Array.prototype.slice(0, number)
. See skip-take.spl.js
Equal to Array.prototype.slice(number)
. See skip-take.spl.js
Take the item while callback(item)
is true. The callback
is DecissionCallback
, same as filterBy
method.
Drop the item while callback(item)
is true. The callback
is DecissionCallback
, same as filterBy
method.
Assign more probs for the current object. The Array
or Generetor
is array of pair<key,value> objects.
const users = [
{ user: 'barney', active: true },
{ user: 'barney', active: true },
{ user: 'fred', active: false },
{ user: 'barney', active: true }
];
ages = [36,37,38,39]
heighs = [10,12,12,13]
users.assignProbs({
age:ages,
heigh:heighs
})
//same as
// Array
// .izip(users, ages, heighs)
// .forEach(([user,age,heigh])=>Object.assign(user,{age,heigh}))
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'barney', age: 37, active: true, heigh: 12 },
// { user: 'fred', age: 38, active: false, heigh: 12 },
// { user: 'barney', age: 39, active: true, heigh: 13 }
// ];