国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

記一次遞歸在我項目中所發揮的作用

n7then / 3357人閱讀

作者:陳大魚頭

github: KRISACHAN

背景

在最近的項目中,有這么一個功能點,就是要獲取在WEB IDE里用戶所寫的注釋中的一段特殊規則,然后解析成一段JS config 對象
例如:

//% width="100px" height="200px"
//% pos.top="50px" pos.left="50px"
//% writable=true
//% q.b.d.w.r.f=30 q.b.d.w.r.a=40

要轉成

{
    width: "100px",
    height: "200px",
    pos: {
        top: "50px",
        left: "50px"
    },
    writable: true,
    q: {
        b: {
            d: {
                w: {
                    r: {
                        f: 30,
                        a: 40
                    }
                }
            }
        }
    }
}

類似的規則

什么是遞歸

來自百度的解釋:
遞歸:程序調用自身的編程技巧稱為遞歸 (recursion)
尾遞歸:如果一個函數中所有遞歸形式的調用都出現在函數的末尾,我們稱這個遞歸函數是尾遞歸的。

就是 復讀機

遞歸怎么寫?

一般

const fibonacci = num => (num === 1 ");

尾遞歸

const fibonacci = (num, total = 1) => (num === 0 ");

Array.reduce

const getArray = count => Array.from({ length: count }, (value, key) => key)
const fibonacci = num => getArray(num).reduceRight((accumulator, currentValue) => accumulator * currentValue)
功能實現 分步實現

    過濾常規內容,獲取特殊的備注信息,去除空格,并且轉成數組

    此時的數組內容為

    [
        "http://% blockId="sloth_servo_write"  block="set servo %channel|degree %degree"",
        "http://% advanced=true",
        "http://% weight=50",
        "http://% degree.min=0 degree.max=180",
        "http://% channel.fieldEditor="gridpicker" channel.fieldOptions.columns=4",
        "http://% a.b.c.d=20 a.b.c.e=222",
        "http://% q.b.d.w.r.f=30 q.b.d.w.r.a=40"
    ]
    

    const code = `
    //% width="100px" height="200px"
    //% pos.top="50px" pos.left="50px"
    //% writable=true
    //% q.b.d.w.r.f=30 q.b.d.w.r.a=40`
    // 獲取特殊注釋數組
    const annotation_array_filter = annotation_item => annotation_item.indexOf("http://%") >= 0;
    // 去除特殊注釋前后的空格
    const annotation_array_remove_space = annotation_item => annotation_item.trim();
    const annotation_array = code.split("
    ")
                                 .filter(annotation_array_filter)
                                 .map(annotation_array_remove_space)
    

    遍歷特殊規則數組,把每一項配置都壓入一個新對象

    此時的新對象內內容為

    {
        a.b.c.d: 20,
        a.b.c.e: 222,
        advanced: true,
        block: "set servo %channel|degree %degree",
        blockId: "sloth_servo_write",
        channel.fieldEditor: "gridpicker",
        channel.fieldOptions.columns: 4,
        degree.max: 180,
        degree.min: 0,
        q.b.d.w.r.a: 40,
        q.b.d.w.r.f: 30,
        weight: 50,
    }
    

      const annotation_array_loop = annotation_item => {
        // 把注釋中的每一項配置轉成對象
        const result_forEach = result_item => {
          let annotation_sub_object = {};
          // 如果特殊注釋數組中的每一項包含多個配置,則扁平化
          const array_flattened = data => {
            const is_array = (this.type(data) === "[object Array]");
            const object_recursion = () => {
              const [key, value] = data.split("=");
              const annotation_sub_object = {};
              try {
                annotation_sub_object[key] = JSON.parse(value);
              } catch (error) {
                annotation_sub_object[key] = JSON.parse(value + """)
              };
              annotation_object = {
                ...annotation_object,
                ...annotation_sub_object
              };
            };
            // 判斷注釋數組項中每一個元素是否有多個配置,如果有則遞歸,否則則注入對象
            is_array ");" ") : result_item);
        const result = annotation_item.replace("http://% ", "")
                                      .split("/" /g")
                                      .map(result_map);
        result_forEach(result);
      };
      let annotation_object = {}; // 承載每一個配置的對象
      annotation_array.forEach(annotation_array_loop);

    把數組里的元素轉成對象

    此時數組內容為

    [
        {
            blockId: "sloth_servo_write"
        },
        {
            advanced: true
        },
        ...
    ]
    

      let main_array = []; // 承載每一個配置的數組
      const annotation_object_keys = Object.keys(annotation_object); // 獲取扁平化后的注釋對象的key
      const annotation_object_keys_loop = annotation_object_key => { // 循環變量每一項注釋
        const annotation_object_key_array = annotation_object_key.split("."); // 把多級對象轉成數組
        const annotation_object_value = annotation_object[annotation_object_key]; // 獲取每一項元素的值
        let sub_object = {}; // 暫時承載配置對象的對象
        const key_reduce = (accumulator, current_value, current_index, array) => { // key值遞歸,對每一項配置進行合并
          if (current_index === 0) { // 如果當前遍歷的元素為第一項,也就是說為配置的頂級對象,所以直接壓入對象,并且輸出
            sub_object[current_value] = (current_index === array.length - 1 ");return sub_object[current_value];
          }
          accumulator[current_value] = {}; // 如果當前遍歷的元素不為第一項,則當前對象元素變為對象
          if (current_index === array.length - 1) { // 如果當前遍歷的元素為數組最后一項,說明是配置對象最底的元素,可以直接賦值
            accumulator[current_value] = annotation_object_value;
          }
          return accumulator[current_value];
        };
        let level_object = annotation_object_key_array.reduce(key_reduce, annotation_object_key_array[0]);
        level_object = undefined; // 清空level_object
        main_array.push(sub_object);
        sub_object = undefined; // 清空sub_object
      }
      annotation_object_keys.forEach(annotation_object_keys_loop);

    遞歸合并對象

    此時的對象為

    {
        a: {b: {…}},
        advanced: true,
        block: "set servo %channel|degree %degree",
        blockId: "sloth_servo_write",
        channel: {fieldEditor: "gridpicker", fieldOptions: {…}},
        degree: {min: 0, max: 180},
        q: {b: {…}},
        weight: 50
    }
    

      const annotation_tree = {};
      const tree_data = (key, value, object) => { // 遞歸合并對象
        if (this.type(value) !== "[object Object]") { // 如果當前傳入元素為對象,則直接壓入對象中
          object[key] = value;
        } else { // 否則繼續遞歸
          if (!object[key]) {
            object[key] = {};
          };
          for (let item in value) {
            tree_data(item, value[item], object[key]);
          }
        };
      };
      const main_array_forEach = item => { // 循環遍歷配置數組
        const key = Object.keys(item)[0];
        const value = Object.values(item)[0];
        tree_data(key, value, annotation_tree);
      };
      main_array.forEach(main_array_forEach);
      main_array = undefined; // 清空main_array
完整代碼
// 代碼轉換器
((wid, dcm) => {
  "use strict";
  const win = wid;
  const doc = dcm;

  // 基礎信息
  const base_info = {
    "version": "0.0.1",
    "author": "kris",
  };

  // 輸出的函數
  const funcs = {
    annotation_parser (annotation) {
      // 配置樹初始化
      this.annotation_tree = {};
      // 獲取特殊注釋數組
      const annotation_array_filter = annotation_item => annotation_item.indexOf("http://%") >= 0;
      // 去除特殊注釋前后的空格
      const annotation_array_remove_space = annotation_item => annotation_item.trim();
      // 循環遍歷特殊注釋數組
      const annotation_array_loop = annotation_item => {
        // 把注釋中的每一項配置轉成對象
        const result_forEach = result_item => {
          let annotation_sub_object = {};
          // 如果特殊注釋數組中的每一項包含多個配置,則扁平化
          const array_flattened = data => {
            const is_array = (this.type(data) === "[object Array]");
            const object_recursion = () => {
              const [key, value] = data.split("=");
              const annotation_sub_object = {};
              try {
                annotation_sub_object[key] = JSON.parse(value);
              } catch (error) {
                annotation_sub_object[key] = JSON.parse(value + """)
              };
              annotation_object = {
                ...annotation_object,
                ...annotation_sub_object
              };
            };
            // 判斷注釋數組項中每一個元素是否有多個配置,如果有則遞歸,否則則注入對象
            is_array ");" ") : result_item);
        const result = annotation_item.replace("http://% ", "")
                                      .split("/" /g")
                                      .map(result_map);
        result_forEach(result);
      };
      let annotation_object = {}; // 承載每一個配置的對象
      annotation.filter(annotation_array_filter)
                .map(annotation_array_remove_space)
                .forEach(annotation_array_loop);
      let main_array = []; // 承載每一個配置的數組
      const annotation_object_keys = Object.keys(annotation_object); // 獲取扁平化后的注釋對象的key
      const annotation_object_keys_loop = annotation_object_key => { // 循環變量每一項注釋
        const annotation_object_key_array = annotation_object_key.split("."); // 把多級對象轉成數組
        const annotation_object_value = annotation_object[annotation_object_key]; // 獲取每一項元素的值
        let sub_object = {}; // 暫時承載配置對象的對象
        const key_reduce = (accumulator, current_value, current_index, array) => { // key值遞歸,對每一項配置進行合并
          if (current_index === 0) { // 如果當前遍歷的元素為第一項,也就是說為配置的頂級對象,所以直接壓入對象,并且輸出
            sub_object[current_value] = (current_index === array.length - 1 ");return sub_object[current_value];
          }
          accumulator[current_value] = {}; // 如果當前遍歷的元素不為第一項,則當前對象元素變為對象
          if (current_index === array.length - 1) { // 如果當前遍歷的元素為數組最后一項,說明是配置對象最底的元素,可以直接賦值
            accumulator[current_value] = annotation_object_value;
          }
          return accumulator[current_value];
        };
        let level_object = annotation_object_key_array.reduce(key_reduce, annotation_object_key_array[0]);
        level_object = undefined; // 清空level_object
        main_array.push(sub_object);
        sub_object = undefined; // 清空sub_object
      }
      annotation_object_keys.forEach(annotation_object_keys_loop);
      const tree_data = (key, value, object) => { // 遞歸合并對象
        if (this.type(value) !== "[object Object]") { // 如果當前傳入元素為對象,則直接壓入對象中
          object[key] = value;
        } else { // 否則繼續遞歸
          if (!object[key]) {
            object[key] = {};
          };
          for (let item in value) {
            tree_data(item, value[item], object[key]);
          }
        };
      };
      const main_array_forEach = item => { // 循環遍歷配置數組
        const key = Object.keys(item)[0];
        const value = Object.values(item)[0];
        tree_data(key, value, this.annotation_tree);
      };
      main_array.forEach(main_array_forEach);
      main_array = undefined; // 清空main_array
    },
  };
  // 引用的資源
  const libs = {};
  // 工具函數
  const tools = {
    // 獲取元素類型
    type (object) {
      return Object.prototype.toString.call(object);
    },
    // 分離傳入的代碼跟配置
    separate_code_and_config (data) {
      data.split("
")
          .forEach(item => {
        item.indexOf("http://%") >= 0 ");return this || (0, eval)("this");
  })();
  if (typeof module !== "undefined" && module.exports) {
    module.exports = code_transformer;
  } else if (typeof define === "function" && define.amd) {
    define([], function () {
      return code_transformer;
    });
  } else {
    !("code_transformer" in _global) && (_global.code_transformer = code_transformer);
  };
})(window, document);

備注:函數體積好大呀,但這只是業務里的一個小小小功能,流下了不會優化代碼的淚水~



如果你、喜歡探討技術,或者對本文有任何的意見或建議,你可以掃描下方二維碼,關注微信公眾號“魚頭的Web海洋”,隨時與魚頭互動。歡迎!衷心希望可以遇見你。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/6931.html

相關文章

  • 一次翻譯站經歷

    摘要:做這個記錄之前,剛完成使用作為公司前端項目的持續交付工具的實踐,打算寫的教程前先把官方文檔扒下來做個翻譯站。在實踐一番后,卡在不能頻密調取翻譯這塊上,項目無法進行下去。 做這個記錄之前,剛完成使用drone作為公司前端項目的持續交付工具的實踐,打算寫的教程前先把官方文檔扒下來做個翻譯站。在實踐一番后,卡在不能頻密調取google翻譯這塊上,項目無法進行下去。最后覺得經歷的過程涉及的內容...

    seasonley 評論0 收藏0
  • 一次XX前端面試

    摘要:面試官說那我問你一個哲學的問題,為什么有數據結構這種東西哇,這是啥,巴拉巴拉扯了一通,大致就是物以類聚,人以群分,先人積累下來的經驗,這些讓我們更方便處理數據啥的。 前因,沒有比摸魚有趣的事了 距離自己被外派(俗稱外包)出去,已經過了快五個月,工作的話,很閑。人啊,一定保持好的習慣,懶惰是會上癮,日常摸魚,懷疑人生,我是誰,我在哪,我要干什么。 中午吃飯的時候,收到了boss直聘的一條...

    Shisui 評論0 收藏0
  • 一次 webpack 打包體積優化

    摘要:手頭做的項目開發得差不多了,而打包配置是一開始粗略配置的,不大的項目打包出來得,所以現在必須進行優化。用于生產環境的打包,設置其為后,這些庫會提供最小體積的文件。這種情況打包后的體積要更小一些。最后打包結果的體積開銷主要就是以上幾項。 手頭做的項目開發得差不多了,而打包配置是一開始粗略配置的,不大的項目打包出來得6MB+,所以現在必須進行優化。 打包結果分析 執行命令 webpack ...

    tomlingtm 評論0 收藏0
  • 一次Docker構建失敗

    摘要:之所以在本地構建,而沒有使用倉庫的,是因為,我們的鏡像采用了國內阿里云的源,再加上某些很奇妙的網絡因素,在中自動構建時,升級總會失敗。然而,在本地再次構建成功。 見字如晤。 前段時間,Node.js 官方發布了Node 8.9.3 LTS版本,并且官網首頁提示新版本有重要安全更新,Important security releases, please update now! ,然后我立...

    joyqi 評論0 收藏0

發表評論

0條評論

n7then

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<