#前置き
//これを
array.filter().map()
//こうしたかった
array.filterMap()
ざっくり言いますと
filter()
やmap()
のcallback関数をジェネレータ関数で処理するようにしただけです。
引数は同様。
最初のyield
でfilter()
、2回目のyield
でmap()
。
「こんなのがあったらいいな」というものなので、実用に耐え得るか否かはわかりません。
#function
const filterMap = (arr, generator) => {
try {
if (!Array.isArray(arr)) {
throw new Error('1st arg : not Array');
}
if (typeof generator!=='function'
|| generator.constructor.name!=='GeneratorFunction') {
throw new Error('2nd arg : not GeneratorFunction');
}
const array = arr.slice();
const result = [];
for (let i=0,m=array.length; i<m; i++) {
const gen = generator(array[i], i, array);
if ( gen.next().value ) {
result.push( gen.next().value );
}
gen.return();
}
return result;
} catch(e) {
console.error(e);
}
};
const arr = [0,1,7,2,1,3,4,5,9,4,5,0,8,3,5,7,4,4];
//値が5のindexを出力
const idx5 = filterMap(arr, function*(x,i,a) {
yield x===5; //filter
yield i //map
});
console.log( idx5 ); // [7, 10, 14]
const chunk = filterMap([...Array(10).keys()], function*(x,i,a) {
yield i%3===0; //filter
yield a.slice(i, i+3); //map
});
console.log( chunk ); //[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
#Array.prototype
if (!Array.prototype.filterMap) {
Object.defineProperty(Array.prototype, 'filterMap', {
value: function(generator) {
try {
if (typeof generator!=='function'
|| generator.constructor.name!=='GeneratorFunction') {
throw new Error('arg is not a GeneratorFunction');
}
const array = this.slice();
const result = [];
for (let i=0,m=array.length; i<m; i++) {
const gen = generator(array[i], i, array);
if ( gen.next().value ) {
result.push( gen.next().value );
}
gen.return();
}
return result;
} catch(e) {
console.error(e);
}
},
});
}
const arr = [0,1,7,2,1,3,4,5,9,4,5,0,8,3,5,7,4,4];
//値が5のindexを出力
const idx5 = arr.filterMap(function*(x,i,a) {
yield x===5; //filter
yield i //map
});
console.log( idx5 ); // [7, 10, 14]
const chunk = [...Array(10).keys()].filterMap(function*(x,i,a) {
yield i%3===0; //filter
yield a.slice(i, i+3); //map
});
console.log( chunk ); //[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
#補足
const idx5 = arr.filterMap(function*(x,i,a) {
yield x===5; //filter
yield i //map
});
処理が単純であればyield* [filter, map]
でまとめられます。
const idx5 = arr.filterMap(function*(x,i,a) {
yield* [x===5, i]; // [filter, map]
});
#私感・妄想
ジェネレータ関数にもアロー関数のような略した書き方がほしい。
妄想.js
//これを
function*(x,i) {
yield* [x===5, i];
});
//こうして
(x,i) *> {
yield* [x===5, i]
};
//更にこうして
(x,i) **> [x===5, i];
//こうなる
const idx5 = arr.filterMap((x,i) **> [x===5, i]);
妄想2.js
//こういうのも
function* increase(n) {
while (true) yield n++;
});
//こう…欲張りすぎか
const increase = n **> n++;
なんてね
#参考