Skip to content

有限集合的添加、映射及过滤 #5

@ilcherry

Description

@ilcherry

有限集合

数学中,一个集合被称为有限集合,简单来说就是元素个数有限 ————《维基百科》

一个有限集合可以通过穷举法将集合里面的元素一一例举出来,这是一条非常重要的原则。在 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 循环,我们可以一一实现
和扩展原生原生方法

那么对有限集合的操作就是"多、变、少"这三个哲学

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions