Attach most of function from lodash to Javascript GeneratorFunction and Array.
npm install gf-js
npm install gf-js --save
`
gf-js
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
`js
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
`js
//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
}
`
What is
GeneratorFunction(GF)?
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
`js
//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
`js
//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);
}
`
How to use?
Open sample folder to see a lot of tutorials
API
$3
Before using, you have to import it in your project first
`js
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 as C# or Python, the Array class does not inherit from Generator, we must deploy the functions for both and write the functions to convert between them. Almost functions start with i return a Generator, and without i return an Array
$3
Convert GeneratorFunction (GF) instance to Array instance
Eg:
`js
function* generator(i) {
yield i;
yield i + 10;
}
let g = generator(5);
let arr = g.toArray(); //arr = [0,1,2,3,4,5]
`
$3
Convert Array instance to Generator
`js
let g = [1,2,3,4,5].toGenerator()
`
now g equal to
`js
function* generator() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}
g = generator()
`
$3
$3
Sum all elements in this Array or GF
`js
console.log([1,2,3].sum()) //1+2+3 = 6
`
$3
$3
Count the number of element
`js
console.log([1,2,3].count()) //3
`
$3
$3
Average of all elements in this array or GF
`js
console.log([1,2,3].avg()) // (1+2+3)/ 3 = 2
`
$3
Implement Array.prototype.forEach(callback) for GF
$3
$3
$3
$3
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
`js
/**
* @typedef {String|Function|Array} GetCallback
*/
`
It can be a function
`js
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
`js
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
`js
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.
$3
$3
The same python build-in zip function
`js
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']]
`
$3
$3
The same python build-in zip function but returns Generator instead of Array
`js
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
`
$3
$3
The same python itertools.chain function.
`js
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
`
$3
$3
The same python itertools.chain function but returns Array instead of GF.
`js
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.
$3
$3
$3
$3
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
`js
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
`js
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
`js
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
`js
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.
$3
$3
$3
$3
Same Array.prototype.filter(callback). A callback not only a function, but also a DecisionCallback.
`js
/**
* A string, a function or a object object.
* @typedef {String|Function|Object.} DecisionCallback
*/
`
callback is function
`js
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]
`
`js
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
`js
users.filterBy(active);
// [
// { user: 'barney', age: 36, active: true, heigh: 10 },
// { user: 'barney', age: 36, active: true, heigh: 12 },
// ]
`
callback is object
`js
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.
$3
$3
Same python build-in range function.
We can user function in two types:
range(_stop_)
range(_start_, _stop_[, _step_])
`js
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]
`
$3
$3
Group all items with the same key in the same group.
The callback parameter is GetCallback. See mapBy method.
`js
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.
$3
$3
The same as groupBy function but instead of return array of items, just return the number of item in the same group.
`js
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.
$3
$3
The same as groupBy but not return the keys, only array of values.
See group-partition-count-distinct.spl for more samples.
$3
$3
$3
$3
Filter the difference items in this Array. The callback parameter is GetCallback. See mapBy method.
`js
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.
$3
$3
$3
$3
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
`js
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.
$3
$3
$3
$3
Special functions of minBy and maxBy. Not apply callback for item.
$3
$3
$3
$3
Insead of returning value, the function return the index of value in GF or Array. See min-max.spl.js
`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']));
`
$3
$3
$3
$3
Special functions of argMinBy and argMaxBy. Not apply callback for item.
$3
$3
$3
$3
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.
`js
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.
$3
$3
Apply Array.prototype.some(callback) to GF.
`js
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
`
$3
$3
Apply Array.prototype.every(callback) to GF.
`js
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
`
$3
$3
$3
$3
Repeats all items in this number of times. If the number is undefined, repeat infinite.
Eg:
`js
for(let item of [1,2].repeat(5)){
console.log(item);
}
//infinite loop
for(let item of [1,2].repeat()){
console.log(item);
}
`
$3
$3
$3
$3
Same as [Array.prototype.slice(begin, [end])](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice). See skip-take.spl.js
$3
$3
$3
$3
Equal to Array.prototype.slice(0, number). See skip-take.spl.js
$3
$3
$3
$3
Equal to Array.prototype.slice(number). See skip-take.spl.js
$3
$3
$3
$3
Take the item while callback(item) is true. The callback is DecissionCallback, same as filterBy method.
$3
$3
$3
$3
Drop the item while callback(item) is true. The callback is DecissionCallback, same as filterBy method.
$3
$3
$3
$3
Assign more probs for the current object. The Array or Generetor is array of pair objects.
`js
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 }
// ];
``