javascript - JavaScript 同时映射和查找:findMap?
问题描述
如果不使用 for 循环,你将如何重写它?
const a = [2, 5, 78, 4];
const expensiveFunction = n => 2 * n;
let result;
// Find the first number
for (let i = 0; i < a.length; i++) {
const r = expensiveFunction(a[i]);
if (r > 100) {
result = r;
break;
}
}
console.log(result);
我天真的方法:
const result = a.map(expensiveFunction).find(x => x > 100);
console.log(result);
但这expensiveFunction
适用于我想避免的所有元素。在上述情况下,我们应该避免运行expensiveFunction(4)
.
有些语言有find_map
(例如Rust),我没有在 lodash 和下划线中找到它。
解决方案
内置map
是贪婪的,所以你必须编写自己的懒惰版本:
const a = [2, 5, 78, 4];
const expensiveFunction = n => {
console.log('expensiveFunction for', n);
return 2 * n
};
function *map(a, fn) {
for(let x of a)
yield fn(x);
}
function find(a, fn) {
for(let x of a)
if (fn(x))
return x;
}
r = find(map(a, expensiveFunction), x => x > 100)
console.log('result', r)
与 stock 不同map
,这map
是一个生成器,并根据需要返回(生成)结果,而不是一次处理整个数组。find
在这个例子中map
是“协程”并玩某种乒乓球游戏,find
要求结果并在被要求map
时提供结果。一旦find
对它得到的东西感到满意,它就会退出map
,因为没有人再要求它的结果了。
您还可以将map
,find
和朋友添加到IteratorPrototype
以使它们可用于所有迭代器并能够使用点表示法:
const IteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
Object.defineProperties(IteratorPrototype, {
map: {
value: function* (fn) {
for (let x of this) {
yield fn(x);
}
},
enumerable: false
},
find: {
value: function (fn) {
for (let x of this) {
if (fn(x))
return x;
}
},
enumerable: false
},
});
//
const a = [2, 5, 78, 4];
const expensiveFunction = n => {
console.log('expensiveFunction', n);
return 2 * n
};
let r = a.values().map(expensiveFunction).find(x => x > 100);
console.log(r)
这是一个基于这种技术的小型库:https ://github.com/gebrkn/armita
推荐阅读
- cloud - 如何访问存储在 COS (IBM Cloud) 中的对象并将其显示到使用 Django 构建并部署在 Cloud Foundry 中的网页上?
- ansible - 当我运行安装命令时,Ansible Galaxy yaml 文件中的集合被忽略
- pandas - 熊猫评估分配方法?
- python - 玩家在 pygame 中不动;没有错误信息
- python - 熊猫分组输出
- android - 如何初始化分页变量
- python-3.x - 如何使用python将字节格式的数据保存为ubuntu 64位中的32位?
- r - 无法在 r 上拟合混合 mlogit 模型
- arrays - 未初始化字符数组的元素的默认值是多少?
- python-3.x - 从远程 ssh 登录运行 mlagents_envs UnityEnvironment