-
Notifications
You must be signed in to change notification settings - Fork 0
Description
有限集合
数学中,一个集合被称为有限集合,简单来说就是元素个数有限 ————《维基百科》
一个有限集合可以通过穷举法将集合里面的元素一一例举出来,这是一条非常重要的原则。在 JavaScript 语言里,类数组、数组和普通对象均可以看为有限集合。因此,我们可以对有限集合进行添加、映射及过滤操作。
本篇博客内容在整体上以抽象现象直击本质,定有不严谨的地方。不过重在学习思想
添加
我定义的添加,即对有限集合的创建、或向其中添加数据,是"多"的操作。
我认为我们声明一个数组、对象变量均属于添加的范畴
const subjects = [];
subjects.push("math");
const blog = {};
blog.title = "有限集合的添加、映射及过滤";通过 push 方法向数组中添加新元素。
我们尝试通过 for 循环实现一个 push 方法
const myPush = (obj, ...args) => {
let len = obj.length,
argsLen = args.length;
for (let i = 0; i < argsLen; i += 1) {
obj[len + i] = args[i];
}
return obj;
};
console.log(myPush([], "1", "2")); // [1, 2]映射
我定义的映射,即改造有限集合中的元素,是“变”的操作。
我们先来看看 underscore 里的 _.map 方法
// underscore.js v1.9.2
_.map = _.collect = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var keys = !isArrayLike(obj) && _.keys(obj),
length = (keys || obj).length,
results = Array(length);
/*
此处的 for 循环是 _.map 方法 核心
为 Array、Set, 那么 result = array[index]
为 Object, 那么 result = object[key]
*/
for (var index = 0; index < length; index++) {
var currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};underscore.js 里的 _.map 方法接受三个参数, 分别是有限集合 obj、迭代函数 iteratee 和该方法的执行上下文 context。该方法先声明一个空数组 results,对 obj 中的元素执行 for 循环操作,每个元素通过 iteratee 函数改造, 并改造后的结果 push 到 results 数组,最后返回这个新数组。而这整个改造过程就是有限集合的映射。
过滤
我定义的映射,即包含删除有限集合中的某些或某个元素、是"少"的操作。
我们先来看看 underscore 里的 _.filter 方法
// underscore.js v1.9.2
_.filter = _.select = function(obj, predicate, context) {
var results = [];
predicate = cb(predicate, context);
/*
通过 for 循环,以新数组形式返回断言函数为真的元素
*/
_.each(obj, function(value, index, list) {
if (predicate(value, index, list)) results.push(value);
});
return results;
};underscore.js 里的 _.filter 方法接受参数参数, 分别是有限集合 obj、断言函数 predicate 和该方法的执行上下文 context。该方法先声明一个空数组 results,对 obj 中的元素执行 for 循环操作,只要该元素通过 predicate 断言函数的结果为 true,就把该元素 push 到 results 数组。实现了有限集合的过滤,即删除了不符合要求的元素,以数组的形式返回符合要求的元素。
再来看看 _.initial 方法
// underscore.js v1.9.2
_.initial = function(array, n, guard) {
return slice.call(
array,
0,
Math.max(0, array.length - (n == null || guard ? 1 : n))
);
};_.initial 接受数组 array 和两个可选参数。该方法使用数组的 slice 方法对数组进行"过滤", 以新数组的形式返回"过滤"后符合要求的元素。 _.initial 在本质上是对数组的过滤、删除不符合要求的数组项。
接着,我们来实现过滤对象 key 的 filterObj 方法
const blog = {
title: "有限集合的添加、映射及过滤",
author: "qinghuanI"
};
const filterObj = function(obj, key) {
return Object.entries(obj)
.filter(item => item[0] !== key)
.reduce((prev, cur) => {
prev[cur[0]] = cur[1];
return prev;
}, {});
};
console.log(filterObj(blog, "title")); //{ author: "qinghuanI" };基石之 for 循环
经过添加、映射和过滤三部分的讲解,我们可以看出,myPush、map、filter、
initial 等方法的实现中都使用了 for 循环。
由此可以总结:for 循环控制语句是实现有限集合操作的基石,通过 for 循环,我们可以一一实现
和扩展原生原生方法
那么对有限集合的操作就是"多、变、少"这三个哲学。