# 字符串操作技巧

# 1、判断字符串是否包含某个字符

# indexOf

indexOf():查找某个字符,有则返回第一次匹配到的位置,否则返回-1
indexOf(要查的元素,开始查询的下标位置)

let str = "123456";
console.log(str.indexOf("1"));   // 输出结果:0
console.log(str.indexOf("7"));   // 输出结果:-1
console.log(str.indexOf("6",6));   // 输出结果:7

注:该方法同样适用于数组操作

# includes

includes():该方法用于判断字符串是否包含指定的子字符串。如果找到匹配的字符串则返回 true,否则返回 false
includes(要查的元素,开始查询的下标位置)

注:使用 includes()比较字符串和字符时是区分大小写。

let str = '123456';

str.includes('1')  // 输出结果:true
str.includes('7')  // 输出结果:false
str.includes('6', 6)  // 输出结果:false

注:该方法同样适用于数组操作

# 2、字符串截取

# slice

slice() 方法用于提取字符串的某个部分,并以新的字符串返回被提取的部分,不改变原字符串。
slice(开始位置,结束位置)
结束位置不填写值时表示到字符串结尾处,负数则代表从结尾开始

let str = "abcdefg";
str.slice(1,6);   // 输出结果:"bcdef" 
str.slice(1);     // 输出结果:"bcdefg" 
str.slice();      // 输出结果:"abcdefg" 
str.slice(-2);    // 输出结果:"fg"
str.slice(6, 1);  // 输出结果:"" 

注:该方法同样适用于数组操作,数组使用时是浅拷贝

# substring

substring() 用于提取字符串中介于两个指定下标之间的字符

str.substring(a, b)
a:需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母。
b:(可选)一个 0 到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。

substring 提取从 a 到 b(不包括)之间的字符。特别地:
如果 a 等于 b,substring 返回一个空字符串。
如果省略 b,substring 提取字符一直到字符串末尾。
如果任一参数小于 0 或为 NaN,则被当作 0。 如果任一参数大于 stringName.length,则被当作 stringName.length。 如果 a 大于 b,则 substring 的执行效果就像两个参数调换了一样。见下面的例子。

var anyString = "Mozilla";

// 输出 "Moz"
console.log(anyString.substring(0,3));
console.log(anyString.substring(3,0));
console.log(anyString.substring(3,-3));
console.log(anyString.substring(3,NaN));
console.log(anyString.substring(-2,3));
console.log(anyString.substring(NaN,3));

// 输出 "lla"
console.log(anyString.substring(4,7));
console.log(anyString.substring(7,4));

// 输出 ""
console.log(anyString.substring(4,4));

// 输出 "Mozill"
console.log(anyString.substring(0,6));

// 输出 "Mozilla"
console.log(anyString.substring(0,7));
console.log(anyString.substring(0,10));

# 3、字符串替换

# replace()

替换指定字符串,并返回一个新的字符串,不改变原字符串

string.replace(searchvalue, newvalue)

searchvalue:一个RegExp 对象或者其字面量,要替换的字符串;
newvalue:用于替换掉第一个参数在原字符串中的匹配部分的字符串,该参数可以为一个function函数

let str = "abcdef";
str.replace("c", "z") // 输出结果:abzdef

# 4、字符串转数字

# parseInt()

解析一个字符串并返回指定基数的十进制整数

parseInt(string, radix)

string:字符串,既被解析的值
radix :可选从 2 到 36,表示字符串的基数。例如指定 16 表示被解析值是十六进制数。请注意,10不是默认值! 由于不是所有的浏览器都是默认采用的10进制方案进行的,因此,在使用 parseInt 时,一定要指定一个 radix。

parseInt("50",10);			  // 输出结果:50

# parseFloat()

函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。

给定值被解析成浮点数。如果给定值不能被转换成数值,则会返回 NaN。

parseFloat("10.01")      // 输出结果:10.01

# 数组操作技巧

# 1、求交集

利用filter测试数组中的每一个元素,在使用includes来判断是否有相同元素,如果有相同的元素则将 返回在一个新的数组中
实例:
let a=[1,2,3,4,5,6],b=[4,5,6,7,8,9];
方法1

 let intersection = a.filter(v => b.includes(v)) // [4,5,6]

方法2

  let aSet = new Set(a)
  let bSet = new Set(b)
  let intersection = Array.from(new Set(a.filter(v => bSet.has(v))))  

# 2、求并集

方法1

  let union = a.concat(b.filter(v => !a.includes(v))) // [1,2,3,4,5,6,7,8,9]

方法2

 let aSet = new Set(a)
 let bSet = new Set(b)
 let union = Array.from(new Set(a.concat(b)))

# 3、求差集

方法1

let difference = a.concat(b).filter(v => !a.includes(v) || !b.includes(v)) // [1,2,3,7,8,9]

方法2

let aSet = new Set(a)
let bSet = new Set(b)
let difference = Array.from(new Set(a.concat(b).filter(v => !aSet.has(v) || !bSet.has(v))))  

# 数据类型转换

数据原型

const tree = [
      {
        name: "一号",
        age: 100,
        children: [
          {
            name: "一号大儿子",
            age: 75,
            children: [
              {
                name: "一号大孙子",
                age: 50,
                children: [{ name: "一号大重孙子", age: 25, children: [] }],
              },
              { name: "一号二孙子", age: 49, children: [] },
            ],
          },
          {
            name: "一号二儿子",
            age: 65,
            children: [
              { name: "一号二儿子的大儿子", age: 38, children: [] },
              { name: "一号二儿子的二儿子", age: 35, children: [] },
            ],
          },
        ],
      },
    ],

# 1、tree树形转list数组

算法的实现主要分为两种:递归和非递归

# 非递归 (队列方式)

 treeConversionListArray(tree) {
      const list = [];
      const queue = [...tree];
      while (queue.length) {
        // 方法一:沿着树的宽度遍历节点。采用队列来辅助完成广度遍历。
        const node = queue.shift();
        // 方法二:沿着树的深度遍历。采用栈来辅助完成深度遍历。
        const node = queue.pop();
        console.log(node);
        const nodeChildren = node.children;
        if (nodeChildren) {
          queue.push(...nodeChildren);
        }
        const { children, ...other } = node;
        list.push(other);
      }
      console.log(list);
      return list;
    },

深度优先遍历(DFS):至上而下的遍历 该方法是以纵向的维度对dom树进行遍历,从一个dom节点开始,一直遍历其子节点,直到它的所有子节点都被遍历完毕之后在遍历它的兄弟节点 foo

广度优先遍历(BFT):逐层深入的遍历 该方法是以横向的维度对dom树进行遍历,从该节点的第一个子节点开始,遍历其所有的兄弟节点,再遍历第一个节点的子节点,完成该遍历之后,暂时不深入,开始遍历其兄弟节点的子节点。 foo

# 递归方式

 treeConversionListArray(tree) {
     const dataList = tree.map((i) => {
        return deepFirstSearch(i, []);
      });
      function deepFirstSearch(node, nodeList) {
        if (node) {
          nodeList.push(node);
          const children = node.children;
          for (let i = 0; i < children.length; i++)
            // 每次递归的时候将 需要遍历的节点 和 节点所存储的数组传下去
            deepFirstSearch(children[i], nodeList);
        }
        return nodeList;
  }

结果

{name: "一号", age: 100},
{name: "一号大儿子", age: 75}
{name: "一号二儿子", age: 65} 
{name: "一号二孙子", age: 49}
{name: "一号二儿子的大儿子", age: 38}
{name: "一号二儿子的二儿子", age: 35}
{name: "一号大孙子", age: 50}
{name: "一号大重孙子", age: 25}

# 2、list数组转tree树形

# 方法一:双层循环

 listConversionTree(list) { 
      list.forEach((child) => {
        const pid = child.pid;
        if (pid) {
          list.forEach((parent) => {
            if (parent.id === pid) {
              parent.children = parent.children || [];
              parent.children.push(child);
            }
          });
        }
      });
      return list.filter((n) => !n.pid);
 }

# 方法二:递归组装

listConversionTree(list) { 
      const tree = [];
      for (const node of list) {
        // 如果没有pid就可以认为是根节点
        if (!node.pid) {
          let p = { ...node };
          p.children = getChildren(p.id, list);
          tree.push(p);
        }
      }
      function getChildren(id, list) {
        const children = [];
        for (const node of list) {
          if (node.pid === id) {
            children.push(node);
          }
        }

        for (const node of children) {
          const children = getChildren(node.id, list);
          if (children.length) {
            node.children = children;
          }
        }

        return children;
      }
      console.log(tree);
      return tree;
 }