js常用方法及写法思路整理

(1)数据、接口整合思维,能合并成一个数组或者接口的尽量合并,代码尽量使用高级一点的写法,不要让代码冗余;
(2)后端返回的数据结构是一维数组,类似于

let resData=[
    {a:'11',b:'11',level:'0'},
    {a:'22',b:'22',level:'1'},
    {a:'33',b:'33',level:'0'},
    {a:'44',b:'44',level:'1'},
    {a:'55',b:'55',level:'1'},
  ]
现在想根据每个对象中的level为0时变成一个二维数组,每个level=0的数组包含后面的level=1的对象,直至遇到下一个level为0的对象,重新生成一个二维数组,并且可以反转数组,且不会更改每个二维数组内部的顺序
if (resData) {
        let j = -1;
        let tempData = resData.reduce((pre, cur) => {
            if (['0', 0].includes(cur?.level)) {
                j++;
                pre.push([]);
            }
            j > -1 && pre[j].push(cur);
            return pre;
        }, []);
        /* 将tempData反转后并按顺序展开成一维数组 */
        let reverseData=tempData.reverse().flat()
        console.log(tempData,reverseData);
    }

(3)对象里面过滤全部符合条件的对象

const obj = {
  	a: 21,
	b: 22,
	c: 23
}
Let aa=Object.fromEntries(Object.entries(obj).filter(([_,i])=>i>21))
console.log(obj,aa);

(4)正则与replace连用

let val='11'
    let myval='112233441121122211144'
    let reg=new RegExp(val,'g')
    let vals=myval.replace(reg,'')

(5)If与switch连用,提高代码可读性

if(){
   switch (key) {
      case value:
        break;
      default:
        break;
    }
}else{}

(6)判定arr.length时,如果一直报错length,那首先要判断arr是否存在,如:if(arr&&!arr.length)或者使用可选链if(arr?.length)
(7)if条件语句可以直接写成

判定条件&&(执行语句);(执行语句)

(8)??(空值合并运算符),es10新增语法,与||类似,都是判断符号左边为false时,直接取符号右边的值,但是??与||的区别在于0值和’ ’(空字符串)判定为true

let a=0,
b=a??'11'
console.log(b);
b=0

(9)禁止a标签的href事件,<a href=’javascript:;’ @click=’deal’>
(10)模板字符串里面不能用this的写法
(11)if用return 或者return early打断,for循环用break打断
(12)处理bug流程?

1、问题复现,定位问题
2、排查出问题点,首先确定是否是语法错误,不是的话找出错误代码位置(通过控制台报错信息、console.log、debugger等手段找出具体问题点,debugger可以执行当前不好执行的部分具体代码,快速了解当前代码是否有错误)
3、将debugger放在该测试的地方,如果在console.log里面sources里面直接执行的话,看看会不会出现弹框,出现弹框说明执行了代码,且点击↘可以直接进行下一行代码运行,鼠标移入this.value可以查看当前的值
4、Vue-develop使用,在测试环境中找到子组件对应的模块,可以看到子组件的状态,如父组件传递给子组件的值有没有传过去等
5、修正问题

(13)有表单验证错误信息展示的需求,但是错误信息默认不展示,当出现错误时展示,可以在表单的下方设置一个空的div,让div先占位着,当错误时显示div的信息,这是一种编程思维,经常能用的到
(14)Foreach里面不能使用splice删除数组中的某一项,因为index会受影响,要使用fliter来进行过滤、选出不符合的项

arr = arr.filter(item => {
        return item.num != 0
    })

(15)将一个内嵌数组转化成一维数组

const deep= function(arr) {
    return [].concat(...arr.map(v=>Array.isArray(v)?deep(v):v))
}
let res=deep([1,[2,3,[7]],[[1],[2,8]]])
或者直接用lodash中的_.flattenDeep()

(16)获取一个1-100的数组

Lodash方法
let arr=_.range(1,101)
手写
let arr=Array(100).fill(1).map((o,v)=>v+1)

(17)将数组的两项数据调换位置

[cloneColumn[5], cloneColumn[0]] = [cloneColumn[0], cloneColumn[5]];

(18)将数组中对象的键名换成自己想要的键名

export const filterArrayProps=(array)=>{
    let newarr=array.map((item) => {
        return Object.assign({},{'label':item.name,'value':item.id})
    })
    return newarr
}

(19)在后端返回的数组中,每个对象中增添一个序号排序字段或者其他字段

export const filterArrayNumSort=(array,pageNum,pageSize)=>{
    let _arr=[]
    array.map((item,index) => {
        _arr.push(Object.assign({},item,{'mysort':(pageNum-1)*pageSize+index+1})) 
    })
    return _arr
}

(19.1)将一个数组1中的对象2中的数组3的对象4提取出来放到一维结构中,也就是放到数组1中

let datas = [
          {
            devzName: "上海浦东新区",
            DEVZCode: "Gasnjkd",
            hits: [
              { IndicName: "GDP", Mvalue: "15456" },
              { IndicName: "GDP增速", Mvalue: "5%" },
            ],
          },
          {
            devzName: "北京大兴经济开发区",
            DEVZCode: "Kjhashd",
            hits: [
              { IndicName: "GDP", Mvalue: "74564" },
              { IndicName: "GDP增速", Mvalue: "6%" },
            ],
          },
          {
            devzName: "合肥经济技术开发区",
            DEVZCode: "Hhskjhd",
            hits: [
              { IndicName: "GDP", Mvalue: "567897" },
              { IndicName: "GDP增速", Mvalue: "8%" },
            ],
          },
        ];

	//第一种写法,双层map
	    const formatData1 = (data) => {
	      let mergeData = data.map((o, i) => {
	        let middleHit = o.hits.map((k, l) => {
	          let source = {};
	          source[k.IndicName] = k.Mvalue;
	          source[k.IndicName + "_guid"] = k.Mvalue + "111";
	          // middleHit.push({ ...source });
	          return source //此处就是直接返回二级数组中的hits中的操作后的每一个对象直接返回了,未合并在一起
	        });
	        return ({ ...o, ...middleHit });
	      });
	      return mergeData;
	    };
	    
		console.log(formatData1(datas));
    // [
    //   {
    //     {GDP: '15456', GDP_guid: '15456111'},
    //     {GDP增速: '5%', GDP增速_guid: '5%111'},
    //     DEVZCode: "Gasnjkd",
    //     devzName: "上海浦东新区",
    //   }
    // ]

        const formatData2 = (data) => {
          let mergeData = data.map((o, i) => {
            let middleHit = o.hits.reduce((pre, cur) => {
              let source = {};
              source[cur.IndicName] = cur.Mvalue;
              source[cur.IndicName + "_guid"] = cur.Mvalue + "111";
              return { ...pre, ...source }; //reduce思想很重要,它把二级数组中的hits中的对象操作后合并成一个对象了,不是分开单独返回的对象
            }, {});
            return { ...o, ...middleHit };
          });
          return mergeData;
        };

        console.log(formatData2(datas));
        // [
        //   {
        //     DEVZCode: "Gasnjkd"
        //     GDP: "15456"
        //     GDP_guid: "15456111"
        //     GDP增速: "5%"
        //     GDP增速_guid: "5%111"
        //     devzName: "上海浦东新区"
        //     hits: (2) [{…}, {…}]
        //   },
        //   {
        //     DEVZCode: "Kjhashd"
        //     GDP: "74564"
        //     GDP_guid: "74564111"
        //     GDP增速: "6%"
        //     GDP增速_guid: "6%111"
        //     devzName: "北京大兴经济开发区"
        //     hits: (2) [{…}, {…}]
        //   }
        // ]

(20)将一个大数组分割成很多个小数组?

 groupslice(array,subGroupLength){
      let index = 0;
      let newArray = [];
      while(index < array.length) {
          newArray.push(array.slice(index, index += subGroupLength));
      }
      return newArray;
或者使用lodash的_.chunk方法
},

(21)将已知数据转化成与其相对应的其他数据

const actions=new Map(
    [//只能为数组
        [1,['success','fail']],
        [2,['success2','fail2']],
        [3,['success3','fail3']],
        ['default',['success4','fail4']],
    ]
)
Console.log(actoins.get(1))

(22)循环获取数组中的值

const a = [1,2,3,4,5]
for(let i=0;i< 100;i++){
  console.log(a[i % (a.length)]);
}

(23)console.log/error/warn/table(将数组内对象结构以表格形式打印出来)/count(记录执行次数)/time、timeEnd(前后包围执行程序,计算执行时间)

(24)查找离今天最近的数据并将此数据的下标返回

 const findClosestData = useMemoizedFn((data: any[]) => {
    let addIdxArray: any[] = [];
    data.map((item, index) => addIdxArray.push(Object.assign({}, item, { mysort: index })));
    let [closest] = addIdxArray.sort((a, b) => {
      //@ts-ignore
      const [aDate, bDate] = [a, b].map((d) => Math.abs(new Date(d?.happenDate) - new Date()));
      return aDate - bDate;
    });
    return closest?.mysort;
  });

(25)数据归类算法

//分类算法
  let arr=[
    {value:'1111',key:'a'},
    {value:'2222',key:'b'},
    {value:'3333',key:'c'},
    {value:'4444',key:'a'},
    {value:'5555',key:'a'},
  ]

  //1、forEach模式
  // let obj={}
  // arr.forEach(o=>{
  //   if(obj.hasOwnProperty(o.key)){
  //     obj[o.key].push(o.value)
  //   }else{
  //     obj[o.key]=[o.value]
  //   }
  // })

  //2、reduce模式
  // const obj=arr.reduce((pre,cur)=>{
  //   if(pre.hasOwnProperty(cur.key)){
  //     pre[cur.key].push(cur.value)
  //   }else{
  //     pre[cur.key]=[cur.value]
  //   }
  //   return pre
  // },{})

  //3、先定义集合,再填充数据
  // const draft={
  //   a: '',
  //   b: '',
  //   c: '',
  // };
  // arr.forEach(o=>{
  //   draft[o.key] = (draft[o.key] ?? '') + `${o.value},`;
  // })
  1、2是可以不需要知道初始的key值的,但是3需要知道初始的对象key值

(25)递归数据

function turnTreeIntoList (array) {
  return array.map(item => [].concat(item, ...item.items)
  )
}

const treeData = [{
    key: '全部',
    title: '全部',
    isLeaf: false,
    children: [{
        key: '数据库',
        title: '数据库',
        isLeaf: false,
        children: [
            {
                key: 'mysql',
                title: 'mysql',
                isLeaf: false,
                children: [
                    {
                        key: '137',
                        title: 'QPS',
                        isLeaf: true,
                    }, {
                        key: '146',
                        title: 'MySQL进程信息',
                        isLeaf: true,
                    },
                ],
            },
            {
                key: 'oracle',
                title: 'oracle',
                isLeaf: false,
                children: [
                    {
                        key: '137',
                        title: 'QPS',
                        isLeaf: true,
                    },
                ],
            },
        ],
    }],
}];

// 获取树的所有祖先节点名称
const getTreeParents = (data) => {
    const parentKey = [];
    data.forEach((item) => {
	/**`在没有限制的情况下,递归运算会无终止地自身调用,所以 在递归运算中要结合 条件语句(if)进行控制``只有在某个条件成立时才允许执行递归,否则不允许调用自身`*/
        if (item.children && item.children.length) {
            parentKey.push(item.key);
            const temp = getTreeParents(item.children);//此处得到的就是children跑完getTreeParents函数得到的parentKey结果["mysql", "oracle"]
            if (temp.length) {
                parentKey.push(...temp);
            }
        }
    });
    return parentKey;
};

const parentKeys = getTreeParents(treeData);
console.log(parentKeys); // ["全部", "数据库", "mysql", "oracle"]
/** 递归初始接口数据,添加level、title、key、checkable字段 */
     const formatTreeData = (array: any[], levelName = 'level', childrenName = 'children') => {
      if (!Array.isArray(array)) return [];
      const recurite = (arr: any[], parentsKeyList: string[], childrenKeyList?: string[], level = 0) => {
        // debugger;
        level++;
        return arr.map((item: Record<string, any>) => {
          item[levelName] = level;
          item['title'] = (
            <div title={item.blockSName} style={{ width: MaxWidthType.get(item.level) }}>
              {item.blockSName}
            </div>
          );
          item['key'] = item.blockCode;
          /** 添加当前节点的所有父级节点集合 */
          item['parentsKeyLists'] = [item.parentBlockCode, ...parentsKeyList];
          const child = item[childrenName];
          /** 给一级树数据添加checkable=false,根据此属性去除一级的复选框*/
          if (item?.level === 1) {
            item['checkable'] = false;
            item.childrenKeyList = [];
          }
          if (childrenKeyList) childrenKeyList.push(item.key);
          if (child && child.length)
            recurite(
              child,
              item['parentsKeyLists'],
              //在一级节点上添加当前所有子节点的key,用来对比checkedKeys,从而实现当板块树下方选中后,一级节点高亮
              item?.level === 1 ? item['childrenKeyList'] : childrenKeyList,
              level,
            );
          return item;
        });
      };

      let finalFormatTreeData = recurite(array, []);

      finalFormatTreeData.forEach((item) => {
        let intersectionData = intersection(item.childrenKeyList, checkedKeys);

        item['title'] = (
          <div
            title={item.blockSName}
            style={{ width: MaxWidthType.get(item.level), color: intersectionData?.length ? '#0171F6' : '#141414' }}
          >
            {item.blockSName}
          </div>
        );
      });

      return finalFormatTreeData;
    };

搜索一组树数据的节点,返回当前子节点和其父级及祖先节点

 const findMenuItem = useMemoizedFn((keyword: string) => {
    const judgeFn = (node: any) => {
      return node.title?.indexOf(keyword) !== -1;
    };
    function _filter(nodes: DataNodeWithLevel[] | undefined, judge: Function) {
      if (!nodes || !nodes.length) return [];
      const child = [];
      for (let i = 0, l = nodes.length; i < l; i++) {
        const node = nodes[i];
        // 自己本身符合条件(如果有匹配的则不用递归了,直接取下面所有的子节点)
        if (judge(node)) {
          child.push(node);
          continue;
        }
        const sub = _filter(node?.children || [], judge);
        // 以下两个条件任何一个成立,当前节点都应该加入到新子节点集中
        // 1. 子孙节点中存在符合条件的,即 sub 数组中有值
        // 2. 自己本身符合条件
        if ((sub && sub.length) || judge(node)) {
          if (node.children) node.children = sub;
          child.push(node);
        }
      }
      return child;
    }
    return _filter(cloneDeep(withLevelData), judgeFn);
  });

(26)前端模拟并发请求

/**
 * 异步任务的并发控制函数
 * @param poolLimit 异步任务的并发限制数
 * @param array 异步任务队列
 * @param iteratorFn 迭代函数,用于实现对每个任务项进行处理
 * @returns
 */
export async function asyncPool(poolLimit: number, array: any, iteratorFn: (item: any) => Promise<any>) {
  const ret = []; // 存储所有的异步任务
  const executing: any[] = []; // 存储正在执行的异步任务

  for (const item of array) {
    /* 调用iteratorFn函数创建异步任务 */
    const p = iteratorFn(item);
    ret.push(p); // 保存新的异步任务

    /* 当poolLimit值小于或等于总任务个数时,进行并发控制 */
    if (poolLimit <= array.length) {
      /* 当任务完成后,从正在执行的任务数组中移除已完成的任务 */
      const e: any = p.finally(() => executing.splice(executing.indexOf(e), 1));
      executing.push(e); // 保存正在执行的异步任务
      if (executing.length >= poolLimit) {
        try {
          await Promise.race(executing); // 等待较快的任务执行完成
        } catch (error) {
          if (process.env.NODE_ENV === 'development') {
            console.error(error);
          }
        }
      }
    }
  }
  return Promise.all(ret); // 最后剩的用 all 跑完
}

//调用
const fetchData = useMemoizedFn(async (lists) => {
    const handleRequest = (item: any) => {
      const { beginTime, endTime, calcBase } = topFilterResult;
      const params = {
        ...item.content,
        beginTime,
        endTime,
        calcBase,
        bondInterestName: item.planId,
      };

      for (const key in params) {
        if (Object.prototype.hasOwnProperty.call(params, key)) {
          const element = params[key];
          if (isArray(element)) params[key] = element.join(',');
        }
      }

      return request
        .post(`/finchinaAPP/v1/finchina-bond/v1/bond/interest/list`, {
          // .post(`/test/v1/bond/interest/list`, {
          data: JSON.stringify(params),
          headers: { 'Content-Type': 'application/json; charset=UTF-8' },
        })
        .then((res: any) => {
          if (res?.data) {
            const { bondInterestName, bondInterestValue } = res.data;
            dispatch((draft) => {
              draft.curveInvest[bondInterestName] = bondInterestValue;
            });
          }
        });
    };
    console.time('fetchTime');
    await asyncPool(6, lists, handleRequest);
    console.timeEnd('fetchTime');
  });
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Pandas中合并数据可以使用两种常用方法:merge和concat。 1. merge方法: merge方法可以根据指定的列将两个DataFrame进行合并,常用的参数有on,how,left_on,right_on,suffixes等。 具体写法如下: ```python # 导入pandas库 import pandas as pd # 创建两个DataFrame df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}) df2 = pd.DataFrame({'A': ['A0', 'A1', 'A6', 'A7'], 'F': ['B4', 'B5', 'B6', 'B7'], 'G': ['C4', 'C5', 'C6', 'C7'], 'H': ['D4', 'D5', 'D6', 'D7']}) # 根据A列进行合并 result = pd.merge(df1, df2, on='A') # 输出合并后的结果 print(result) ``` 输出结果为: ``` A B C D F G H 0 A0 B0 C0 D0 B4 C4 D4 1 A1 B1 C1 D1 B5 C5 D5 ``` 2. concat方法: concat方法可以将两个或多个DataFrame沿着行或列的方向进行合并,常用的参数有axis,join,keys等。 具体写法如下: ```python # 导入pandas库 import pandas as pd # 创建两个DataFrame df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'], 'B': ['B0', 'B1', 'B2', 'B3'], 'C': ['C0', 'C1', 'C2', 'C3'], 'D': ['D0', 'D1', 'D2', 'D3']}) df2 = pd.DataFrame({'E': ['E4', 'E5', 'E6', 'E7'], 'F': ['F4', 'F5', 'F6', 'F7'], 'G': ['G4', 'G5', 'G6', 'G7'], 'H': ['H4', 'H5', 'H6', 'H7']}) # 沿着列的方向进行合并 result = pd.concat([df1, df2], axis=1) # 输出合并后的结果 print(result) ``` 输出结果为: ``` A B C D E F G H 0 A0 B0 C0 D0 E4 F4 G4 H4 1 A1 B1 C1 D1 E5 F5 G5 H5 2 A2 B2 C2 D2 E6 F6 G6 H6 3 A3 B3 C3 D3 E7 F7 G7 H7 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值