js面试题

1.对象obj = { ‘a.b.c’: 1, ‘a.d’: 2, ‘e’: 3}变为obj={a:{b:{c: 3}, d: 2},e:3} (掘金上看的)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    let obj = {
        'a.b.c': 1,
        'a.d': 2,
        'e': 3
    }
    let newObj = {};
    let keysList = Object.keys(obj).map(item => {
        return item.split('.');
    });

    let res = null;
    var keys = '';
    keysList.forEach(item => {
        keys = '';
        for (var i = 0; i < item.length; i++) {
            keys = keys ? keys + '.' + item[i] : item[i]; // 累加字段
            getObjKeys(item[i], i, item.length);
        }
    })

    function getObjKeys(item, index, length) {
        if (length === 1 && index === length - 1) {
            // 1.如果只有一项的话
            newObj[item] = obj[item];
        } else {
            if (index === 0) {
                // 如果是第1项判断有没有
                if (!newObj[item]) {
                    newObj[item] = {}
                }
                res = newObj[item];
            } else if (index !== length - 1) {
                // 2.如果有多项时
                if (!res[item]) {
                    res[item] = {}
                }
                res = res[item]
            } else {
                // 最后进行判断,如果已经到了最后一项的话就要赋值了
                res[item] = obj[keys];
            }
        }
    }

    console.log(newObj)
</script>

</html>

2.扁平化数组: const array = [1,[2,[[3,4],5]]];输出array=[1,2,3,4,5] (知乎上看的)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>

<script>
    const array = [1,[2,[[3,4],5]]];
    let newArray = [];
    array.forEach(item => {
        if (item instanceof Array === true) {
            getFun(item);
        } else {
            newArray.push(item);
        }
    })
    function getFun(array) {
        array.forEach(item => {
            if (item instanceof Array === true) {
                getFun(item);
            } else {
                newArray.push(item);
            }
        })
    }
    console.log(newArray);
</script>
</html>




/*数组扁平化: 取出嵌套数组(多维)中的所有元素放到一个新数组(一维)中 如: [1, [3, [2, 4]]] ==> [1, 3, 2, 4] */
/*方法一: 递归 + reduce() + concat() + some() */
function flatten1(array) {
    return array.reduce((pre, item) => {
        if (Array.isArray(item) && item.some((cItem => Array.isArray(cItem)))) {
            return pre.concat(flatten1(item))
        } else {
            return pre.concat(item)
        }
    }, [])
}

/*方法二: ... + some() + concat() */
function flatten2(arr) {
    // 只要arr是一个多维数组(有元素是数组)
    while (arr.some(item => Array.isArray(item))) {
        // 对arr进行降维 
        arr = [].concat(...arr)
    }
    return arr
}

方法三:arr.flat(): 将多维数组转为一维数组(也称为: 数组扁平化) [1, [2, 3]] ==> [1, 2, 3]
let arr1 = [1, [3, [2, 4]]];
function flatten2(arr) {
    // 只要arr是一个多维数组(有元素是数组)
    while (arr.some(item => Array.isArray(item))) {
        // 对arr进行降维 
        arr = arr.flat()
    }
    return arr
}
flatten2(arr1)

3. let arr = [ { id: 4, name: ‘部门4’, pid: 3 }, { id: 5, name: ‘部门5’, pid: 4 }, { id: 1, name: ‘部门1’, pid: 0 }, { id: 2, name: ‘部门2’, pid: 1 }, { id: 3, name: ‘部门3’, pid: 1 }, ]变为树形结构 (知乎上看的)

树形结构

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    let arr = [
        { id: 4, name: '部门4', pid: 3 },
        { id: 5, name: '部门5', pid: 4 },
        { id: 1, name: '部门1', pid: 0 },
        { id: 2, name: '部门2', pid: 1 },
        { id: 3, name: '部门3', pid: 1 },
    ]

    arr.forEach(item => {
        for (var value of arr) {
            if (item.id === value.pid) {
                value.type = 1
                item.children ?  item.children.push(value) : item.children = [value];
            }
        }
    })
    let array = arr.find(item => {
        return !item.type;
    })
    console.log([array]);
</script>

</html>

4. 写三个Promise函数,如果有错误就停止执行,没有错误按顺序执行(阿里外包)

function fun1(){
    return new Promise(function(resolve, reject){
        resolve('fun1返回的数据')
    })
}
function fun2(){
    return new Promise(function(resolve, reject){
        // resolve('fun2返回的数据')
        resolve()
        // reject('fun2错误')
    })
}
function fun3(){
    return new Promise(function(resolve, reject){
        // reject('fun3错误')
        resolve('fun3返回的数据')
    })
}
fun1().then(function(data) {
    console.log(data)
    return fun2()
}).then(function(data) {
    console.log(data)
    return fun3()
}).then(function(data){
    console.log(data)
})

fun2错误则fun3不执行
在这里插入图片描述
没有错误都执行
在这里插入图片描述

5. 数组去重

方法一:使用fliter/find, 如果有fliter返回数组包含项[查找到的数据],如果没有则返回[], find如果有返回当前查找项,如果没有返回undefined

let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
let arrayNew = []
array.map(item => {
    const result = arrayNew.find(items => item === items)
    if (!result) {
        arrayNew.push(item)
    }
})
console.log(arrayNew)

在这里插入图片描述
方法二:
arrayNew.includes(item)需要查找值,includes返回true/false

let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
let arrayNew = []
array.map(item => {
    const result = arrayNew.includes(item)
    console.log(result)
    if (!result) {
        arrayNew.push(item)
    }
})
console.log(arrayNew)

在这里插入图片描述
方法三: Set value1, value2, value3 value不会重复, 如果有自动过滤掉
new Set(array)结果为{1, 2, 3, 5, 4, 6, 8, 7, 9},Array.from会添加个[]空数组并把值放进去

let array = [1,1,2,3,5,4,6,8,6,8,7,3,9];
Array.from(new Set(array)) // (9) [1, 2, 3, 5, 4, 6, 8, 7, 9]

方法四:使用对象属性名的唯一性来保证不重复

// 数字或字符串数组去重,效率高
function unique(arr) {
      var result = {}; // 利用对象属性名的唯一性来保证不重复
      for (var i = 0; i < arr.length; i++) {
           if (!result[arr[i]]) {
               result[arr[i]] = true;
           }
      }
      return Object.keys(result); // 获取对象所有属性名的数组
}

方法五:使用数组的indexOf(item) === -1,如果等于-1则是没有

let arr1 = [1, 1, 2, 3, 5, 2, 6, 5 , 4];
let newArray = [];
for(var i = 0; i< arr1.length; i++) {
    if(newArray.indexOf(arr1[i]) === -1) {
        newArray.push(arr1[i]);
    }
}
console.log(newArray)

方法六:使用Map数据结构去重

let map = new Map();
let array = [1, 2, 3, 2, 3, 5, 1, 4, 6];
let newArray = []; // let newArray = new Array();
for (let i =0; i<array.length; i++) {
    if(map.has(array[i])) {
        // 如果有该key值
        map.set(array[i], true);
    } else {
        map.set(array[i], false);
        newArray.push(array[i]);
    }
}
console.log(newArray)

6. 写个函数判断两个对象是否相等,key与值相等 (喜茶外包)

方法一: for(let key in obj) 使用for…in循环对象,delete key删除对象中某一项,再用Object.keys(obj)获取对象的key值,返回[]key的数组
当obj1循环结束时意味着obj2也要比较完,为空对象

let obj1 = {l1:1, l3:3, l4: 4, l2:2}
let obj2 = {l1:1, l2:2, l3:3, l4: 4}
function fun() {
    for (let key1 in obj1) {
        for(let key2 in obj2) {
            if (key1 === key2) {
                // 循环判断key是否相等
                if (obj1[key1] === obj2[key2]) {
                    // 判断key的值是否相等,如果相等则删除obj2中这项
                    delete obj2[key2]
                }
            }
        }
    }
    if (!Object.keys(obj2).length) {
        // 如果obj2对象为空那就说明与obj1相等
        return true
    }
    return false
}
console.log(fun())

当key与值相等时,即使位置换了也是为ture
在这里插入图片描述
位置没有变化,如果key或者值不相等为false
在这里插入图片描述
----------------------------------------------------------------------优化----------------------------------------------------------
如果对象中出现两个相同的key,值不同,那就用个值来计数

function fun() {
    let obj1 = {l1:1, l1:2, l3:3, l4:4}
    let obj2 = {l2:2, l1:1, l3:3, l4:4}
    let count = Object.keys(obj1).length // obj1 keys数组的长度
    if (Object.keys(obj1).length !== Object.keys(obj2).length) {
    	// 如果两个对象的key值数组不等则直接返回false
        return false
    }
    for (let key1 in obj1) {
        for(let key2 in obj2) {
            if (key1 === key2) {
                // 循环判断key是否相等
                if (obj1[key1] === obj2[key2]) {
                    // 判断key的值是否相等,如果相等则删除obj2中这项
                    // delete obj2[key2]
                    count --
                }
            }
        }
    }
    // if (!Object.keys(obj2).length) {
    //     // 如果obj2对象为空那就说明与obj1相等
    //     return true
    // }
    if (!count) {
        // 如果count为0那就说明都循环对应完毕
        return true;
    }
    return false
}
console.log(fun())

在这里插入图片描述
方法二: 使用Object.entries获取两个对象的[key, value]数组值

function fun() {
    let obj1 = {l1:1, l2:2, l3:3, l4:4}
    let obj2 = {l1:1, l2:2, l3:3, l4:5}
    const objValues1 = Object.entries(obj1)
    const objValues2 = Object.entries(obj2)
    if(objValues1.length !== objValues2.length) {
        // 长度不相等返回false
        return false
    }
    let count = objValues1.length
    objValues1.forEach(item => {
        objValues2.forEach(items =>{
            if (item[0] === items[0]) {
                // 循环,如果key值相等
                if(item[1] === items[1]) {
                    // 如果值也相等
                    count -- 
                }
            }
        })
    })
    if (!count) {
        // 如果count为0则相等
        return true
    }
    return false
}
fun()

在这里插入图片描述
方法三: Object.is(value1, value2): 判断2个值是否完全一样 NaN===NaN
跟上面的一样,先判断两个obj的key是否相等再判断值是否相等,当obj1循环完毕再看记步数count是否等于0

let obj1 = {l1: 1, l2: 1}
let obj2 = {l1: 1, l2: 2}
console.log(Object.is(obj1.l1, obj1.l1)) // true

7. 有一个id为list的列表,要求:往其中插入100个节点,点击每个列表项时,能弹出是第几个。事件代理(事件委托)

<ul id="list"></ul>
<script>
  (()=>{
    const container = document.getElementById('list')
    // 创建文档片段,此时还没有插入到DOM树中
    const fragments = document.createDocumentFragment() // 离线加载,不会触发重排重绘
    // 动态创建节点并组合到文档片段中
    for(let i = 0; i < 100; i++){
      const li = document.createElement("li")
      li.innerHTML = `item-${i+1}`
      fragments.appendChild(li)
    }
    // 一次性插入DOM树中
    container.appendChild(fragments)
    container.addEventListener('click',function(e){
      if(e.target.tagName === 'LI'){
        alert(e.target.innerHTML)
      }
    })
  })()
</script>

如果是插入50000个节点呢?

<ul id="list"></ul>
<script>
  (()=>{
    const container = document.getElementById('list')
    const TOTAL = 50000
    const BATCH_SIZE = 10 // 每批插入节点次数,越大越卡
    const BATCH_COUNT = TOTAL / BATCH_SIZE // 需要批处理多少次
    let batchDone = 0 // 已经完成的批处理个数
 
    function appendItems(){
      const fragments = document.createDocumentFragment()
      for(let i = 0; i < BATCH_SIZE; i++){
        const item = document.createElement("li")
        item.innerHTML = `item-${(batchDone * BATCH_SIZE ) + i + 1}` 
        fragments.appendChild(item)
      }
      container.appendChild(fragments)
      batchDone += 1
      batchAppend()
    }
 
    function batchAppend(){
      if(batchDone < BATCH_COUNT){
        window.requestAnimationFrame(appendItems)
      }
    }
 
    batchAppend()
 
    container.addEventListener('click',function(e){
      if(e.target.tagName === 'LI'){
        alert(e.target.innerHTML)
      }
    })
  })()
</script>

8. 假设有一串字符串,拿到最多连续的次数,比如:acbac, ac连续出现次数2次;abcacabacaaacd中ac连续出现3次,ksjdxsksdxskdx中dx连续出现3次 (忘记名字的公司)

<script>
  let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
  function soluction(str) {
    let array = []; // 记录有多少种组合情况,
    let count = 0; // 记录当前字符串出现的次数;
    let maxCount = 0; // 记录子字符串出现最多的次数;
    let childstr = ''; // 记录当前出现最多次数的是哪个字符串
    for (let i = 0; i < str.length; i++) {
      // 第一层循环先从第一个开始找
      for (let y = str.length; y > i + 1; y--) {
        array.push(str.slice(i, y))
      }
    }
    // 设置一个递归函数
    function digui(str, item) {
      if (str.includes(item)) {
        // 如果还有则再递归
        count++;
        digui(str.slice(str.indexOf(item) + item.length), item);
      } else {
        // 如果没有的话就return
        return count;
      }
    }
    // 循环数组,找出子字符在字符串中出现的次数
    array.forEach(item => {
      count = 0; // 每次循环重新记录
      if (str.includes(item)) {
        count++;
        if (str.slice(str.indexOf(item) + item.length)) {
          digui(str.slice(str.indexOf(item) + item.length), item);
        }
      }
      if (count > maxCount) {
        childstr = item;
        maxCount = count
      }
    })
    console.log(childstr, maxCount)
    return maxCount; // 输出最多次数
  }
  soluction(str);
</script>

如果只需要出现次数最多的,要次数的话上面的可以实现。
优化:如果出现两个字符串都是3次的,把这些字符串找出来 定义个对象,把每个字符串出现的次数用键值对保存,最后再循环对象,找到最大值的key

let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
  function soluction(str) {
    let array = []; // 记录有多少种组合情况,
    let count = 0; // 记录当前字符串出现的次数;
    let maxCount = 0; // 记录子字符串出现最多的次数;
    let childstr = ''; // 记录当前出现最多次数的是哪个字符串
    let obj = {}; // 定义一个对象
    for (let i = 0; i < str.length; i++) {
      // 第一层循环先从第一个开始找
      for (let y = str.length; y > i + 1; y--) {
        array.push(str.slice(i, y))
      }
    }
    // 设置一个递归函数
    function digui(str, item) {
      if (str.includes(item)) {
        // 如果还有则再递归
        count++;
        digui(str.slice(str.indexOf(item) + item.length), item);
      } else {
        // 如果没有的话就return
        return count;
      }
    }
    // 循环数组,找出子字符在字符串中出现的次数
    array.forEach(item => {
      count = 0; // 每次循环重新记录
      if (str.includes(item)) {
        count++;
        if (str.slice(str.indexOf(item) + item.length)) {
          digui(str.slice(str.indexOf(item) + item.length), item);
        }
      }
      obj[item] = count; // 把当前的保存起来
      if (count > maxCount) {
        childstr = item;
        maxCount = count
      }
    })
    console.log(childstr, maxCount)
    // 循环对象 for in
    let objArray = []; // 定义个数组用来装出现次数最多的key值
    for (let key in obj) {
		if (obj[key] === maxCount) {
			objArray.push(key); // 把key值装进去, 对象的key值唯一性,几乎不会出现重复的key
		}
	}
	// 循环完毕,objArray 装的就是出现次数最多的key值
	console.log(objArray);
    return maxCount; // 输出最多次数
  }
  soluction(str);
</script>

9.判断一个字符串中是否有某个key字符串,没有返回null,有则返回数组 (同上)

<script>
  let str = 'ksjdxsksdxskdx'; // 假设有这么个字符串,找出连续最多的字符次数
  let key = 'dx';
  let array = [];
  function soluction(str) {
    if (str.indexOf(key) === -1) {
      // 不存在则返回null
      return null;
    }
    // 存在则返回数组
    function fun(str) {
      if (str.includes(key)) {
        array.push(key);
        if (!str.slice(str.indexOf(key) + key.length)) {
          return array;
        }
        return fun(str.slice(str.indexOf(key) + key.length));
      } else {
        return array;
      }
    }
    const resultArray = fun(str);
    console.log(resultArray);
  }
  soluction(str);
</script>

10.冒泡排序 (丰巢)

// ---------------从小到大排----------------
<script>
  const array = [1, 5, 9, 11, 2, 6, 3, 7, 8, 4];
  // const array = [5, 6, 9, 7, 4, 3, 8, 2, 1];
  let maxValue = 0; // 设置一个最大的接收属性
  // 冒泡排序:从小到大排,思路:数组循环,当前项与后一项比较,如果当前项大于后一项,则把当前项赋值给大值,然后再把后项给当前项
  for (let i = 0; i < array.length; i++) {
    for (let j = 0; j < array.length; j++) {
      if (array[j] > array[j + 1]) {
        // 如果当前项大于后一项,则要把当前项记录,并跟第二项换位置
        maxValue = array[j];
        array[j] = array[j + 1];
        array[j + 1] = maxValue;
      }
    }
  }
  console.log(array);
</script>

// ---------------从大到小排-----------------思路:变的只是存储的是小值,如果当前项小于后一项,就把当前项赋值给小值属性标志,再把当前项与后一项对换位置
<script>
  const array = [1, 5, 9, 11, 2, 6, 3, 7, 8, 4];
  // const array = [5, 6, 9, 7, 4, 3, 8, 2, 1];
  let minValue = ''; // 设置一个最小的接收属性
  // 冒泡排序:从小到大排,思路:数组循环,当前项与后一项比较,如果当前项大于后一项,则把当前项赋值给大值,然后再把后项给当前项
  for (let i = 0; i < array.length; i++) {
    for (let j = 0; j < array.length; j++) {
      if (array[j] < array[j + 1]) {
        // 如果当前项大于后一项,则要把当前项记录,并跟第二项换位置
        minValue = array[j];
        array[j] = array[j + 1];
        array[j + 1] = minValue;
      }
    }
  }
  console.log(array);
</script>

11.?foo=bar&abc=123&abc=xyz输出{foo:‘bar’, abc: [‘123’, ‘xyz’]}, {foo:‘bar’, abc: [‘123’, ‘xyz’]}输出?foo=bar&abc=123&abc=xyz (阿里外包)

1.?foo=bar&abc=123&abc=xyz输出{foo:‘bar’, abc: [‘123’, ‘xyz’]}

function UrlTools(url) {
    let array = url.split('?')[1].split('&');
    let obj = {};
    array.forEach(item => {
      let itemArray = item.split('=');
      if (obj[itemArray[0]]) {
        // 如果已经存在则用数组装起来
        let arrayComm = [];
        arrayComm = [obj[itemArray[0]]];
        obj[itemArray[0]] = [...arrayComm, itemArray[1]]
      } else {
        obj[itemArray[0]] = itemArray[1];
      }
    });
    return obj;
  }
  UrlTools('?foo=bar&abc=123&abc=xyz');

2.{foo:‘bar’, abc: [‘123’, ‘xyz’]}输出?foo=bar&abc=123&abc=xyz

function UrlTools(obj) {
  	let params = '?';
    for (let key in obj) {
      // 遍历对象
      if (Object.prototype.toString.call(obj[key]) === '[object Array]') {
        // 如果是数组就要循环数组
        obj[key].forEach(item => {
          if (params === '?') {
            // 如果是第一项不用加&
            params = `${params}${key}=${item}`
          } else {
            params = `${params}&${key}=${item}`
          }
        });
      } else {
        if (params === '?') {
          // 如果是第一项就不要加&
          params = `${params}${key}=${obj[key]}`
        } else {
          // 如果不是第一项要加&
          params = `${params}&${key}=${obj[key]}`
        }
      }
    }
    console.log(params)
  }
  UrlTools({
    foo: 'bar',
    abc: ['xyz', '123'],
  });

-----------------------------------优化---------------------------
原本的题目是:
class UrlTools {}
console.log(‘parse’, UrlTools.parse(‘?foo=bar&abc=123&abc=xyz’));
console.log(‘styify’, UrlTools.styify({
foo: ‘bar’,
abc: [‘xyz’, ‘123’],
}));
时间紧迫,没有想起class,所以用js做了,交卷以后才想起class的做法

//static parse需要在方法前加static这样可以不用实例class,直接用UrlTools.xxx();如果没有加static的方法需要实例后才能调用:
let urlTools = new UrlTools(); urlTools.parse(), urlTools .styify();

class UrlTools {
    static parse(url) {
      let array = url.split('?')[1].split('&');
      let obj = {};
      array.forEach(item => {
        let itemArray = item.split('=');
        if (obj[itemArray[0]]) {
          // 如果已经存在则用数组装起来
          let arrayComm = [];
          arrayComm = [obj[itemArray[0]]];
          obj[itemArray[0]] = [...arrayComm, itemArray[1]]
        } else {
          obj[itemArray[0]] = itemArray[1];
        }
      });
      return obj;
    }
    static styify(obj) {
      let params = '?';
      for (let key in obj) {
        // 遍历对象
        if (Object.prototype.toString.call(obj[key]) === '[object Array]') {
          // 如果是数组就要循环数组
          obj[key].forEach(item => {
            if (params === '?') {
              // 如果是第一项不用加&
              params = `${params}${key}=${item}`
            } else {
              params = `${params}&${key}=${item}`
            }
          });
        } else {
          if (params === '?') {
            // 如果是第一项就不要加&
            params = `${params}${key}=${obj[key]}`
          } else {
            // 如果不是第一项要加&
            params = `${params}&${key}=${obj[key]}`
          }
        }
      }
      return params;
    }
  }
  console.log('parse', UrlTools.parse('?foo=bar&abc=123&abc=xyz'));
  console.log('styify', UrlTools.styify({
    foo: 'bar',
    abc: ['xyz', '123'],
  }));

12.react自定义hooks写一个计数器 (同上,阿里外包)

// 简单的计数器,题目是这样的
  function Counter() {
    const [count, setCount] = useState(0);

    useInterval(() => {
      setCount(count + 1);
    }, 1000);

    return <h1>{count}</h1>;
  }

  function useInterval(callback, delay) {
    // 你的代码
  }
function Counter() {
  const [count, setCount] = useState(0);
  
  useInterval(() => {
    setCount(count + 1);
    }, 1000);
  
    return <h1>{count}</h1>;
  }
  
  function useInterval(callback, delay) {
    // 你的代码
    // let timer = null;
    // if (timer) {
      // clearTimeout(timer)
    // }
    // timer = setTimeout(callback, delay);
    // useEffect(() => {
      // return() => { // 清除副作用,在这里面清除定时器
        // clearTimeout(timer)
      // }
    // })

	useEffect(() => {
      let timer = null;
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(callback, delay);
      return() => { // 清除副作用,在这里面清除定时器
        clearTimeout(timer)
      }
    });
  }
function App() {
  return (
    <div className="App">
      <Counter />
    </div>
  );
}

export default App;

13.给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。(腾讯外包)

// 给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。
// 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
// (要求ta只能操作数组,不能转成数字直接加一)
// 示例 1:
// 输入: [1, 2, 3] 输出: [1, 2, 4]
// 示例 2:
// 输入: [4, 3, 2, 1] 输出: [4, 3, 2, 2]
// 示例 3:
// 输入:[9] 输出:[1, 0]
// 示例 4:
// 输入:[9, 9, 9] 输出:[1, 0, 0, 0]
// 1. [9, 8, 9] 输出 [9, 9, 0]

// *这个题目就是数组的最后项加1,如果为9, 9 +1 =10,那么当前位为0,前一位+1;

~~悲惨的是我当时脑子一片空白没写出来,晚上沉下心来突然想到怎么做了~

<script>
  //   给定一个由整数组成的非空数组所表示的非负整数如[1, 2, 3],在该数的基础上加一。
  //     最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
  // (要求ta只能操作数组,不能转成数字直接加一)
  // 示例 1:
  //     输入: [1, 2, 3]  输出: [1, 2, 4]
  // 示例 2:
  //     输入: [4, 3, 2, 1] 输出: [4, 3, 2, 2]
  // 示例 3:
  //     输入:[9] 输出:[1, 0]
  // 示例 4:
  //     输入:[9, 9, 9] 输出:[1, 0, 0, 0]
  // 1. [9, 8, 9] 输出 [9, 9, 0]

  // ******这个题目就是数组的最后项加1,如果为9, 9 +1 =10,那么当前位为0,前一位+1;*****
  function getDatas(array) {
    let newArray = [];
    // 思路从后往前循环,逢9 + 1 =10打标记,如果循环完毕标记为true则在数组前加1
    let isAddNum = false; // 用一个值来记录是否等于10需要往前+1;
    for (let i = array.length - 1; i >= 0; i--) {
      if (isAddNum) { // 判断是否要+1
        // 加完1后判断是否为10
        let newValue = array[i] + 1;
        if (newValue == 10) {
          isAddNum = true;
          newArray.unshift(0);
        } else {
          isAddNum = false;
          newArray.unshift(newValue);
        }
      } else {
        if (i === array.length - 1) { // 如果是最后一项需要+1
          // 先判断最后项加1之后是否是10,是打标记,需要往前进1,并把当前项置为0;
          if (array[i] + 1 == 10) {
            isAddNum = true
            newArray.unshift(0);
          } else {
            isAddNum = false;
            newArray.unshift(array[i] + 1);
          }
        } else {
          isAddNum = false;
          newArray.unshift(array[i]); // 如果是不需要加+1的直接返回该项
        }
      }
    }
    // 循环结束后判断isAddNum标记是否为true;为true要在数组最前面+1
    if (isAddNum) {
      newArray.unshift(1);
    }
    return newArray;
  }
  console.log(getDatas([9, 9, 9, 9]));
</script>

-----------------------优化-----------------把相同的代码整合一下

<script>
  function getDatas(array) {
    let newArray = [];
    // 思路从后往前循环,逢9 + 1 =10打标记,如果循环完毕标记为true则在数组前加1
    let isAddNum = false; // 用一个值来记录是否等于10需要往前+1;
    for (let i = array.length - 1; i >= 0; i--) {
      if (isAddNum || i === array.length - 1) { // 判断是否要+1,最后一项或者最后一项逢9打标记的加1
        // 加完1后判断是否为10
        const newValue = array[i] + 1;
        if (newValue == 10) {
          isAddNum = true;
          newArray.unshift(0);
        } else {
          isAddNum = false;
          newArray.unshift(newValue);
        }
      } else {
        newArray.unshift(array[i]); // 如果是不需要加+1的直接返回该项
      }
    }
    // 循环结束后判断isAddNum标记是否为true;为true要在数组最前面+1
    if (isAddNum) {
      newArray.unshift(1);
    }
    return newArray;
  }
  console.log(getDatas([5, 3, 9, 1]));
</script>

14.反转有符号整数

写出函数 function reverseNum( num ) 能够反转数字
输入: x = 123
输出: 321

输入: x = -123
输出: -321

输入: x = 120
输出: 21

function reverseNum( num ) {
        num = num.toString();
        let result = '';
        for (let i = num.length; i > 0; i--) {
            if (isNaN(num.substr(i - 1, 1))) {
                result = num.substr(i - 1, 1) + result
            } else {
                result = result + num.substr(i - 1, 1);
            }
        }
        return +result;
    }
    console.log(reverseNum(120));

15.URL解析器(与11相反)

写一个parse的函数将url解析器,将url转换成指定的结构
如:将 http://www.a.com?key1=1&key2=2&key1=3&test=4#haha
转换成:
{
protocol: ‘http’,
hostname: ‘www.a.com’,
pathname: ‘/test’,
search: ‘?key1=1&key2=2&key1=3&test=4’,
searchParams: {
key1: [‘1’, ‘2’]
key2: ‘2’,
test: ‘4’
},
hash: ‘#haha’,
}

const case1 = 'http://www.a.com/test?key1=1&key2=2&key1=3&test=4&key1=5#haha'
function parse(url) {
    const hash = case1.split('#');
    const params = hash[0].split('?');
    let paramsList = params[1].split('&');
    let searchParams = {}
    paramsList.forEach(item => {
        const subItems = item.split('=');
        const [key, value] = subItems;
        if (searchParams[key]) {
            // 如果已经存在了,先判断他的值
            if (Array.isArray(searchParams[key])) {
                // 如果是数组,直接追加
                searchParams[key].push(value);
            } else {
                searchParams[key] = [searchParams[key], value];
            }
        } else {
            searchParams[key] = value;
        }
    });
    const search = params[1];
    const httpUrl = params[0].split('//');
    const hostUrl = httpUrl[1].split('/');
    return {
        protocol: httpUrl[0],
        hostname: hostUrl[0],
        pathname: hostUrl[1],
        search,
        searchParams,
        hash: `#${hash[1]}`
    }
}

console.log(parse(case1));

16.[1,1,‘true’,‘true’,true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,‘NaN’, 0, 0, ‘a’, ‘a’,{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}]去重

const arr = [1,1,‘true’,‘true’,true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,‘NaN’, 0, 0, ‘a’, ‘a’,{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}];
去重之后的结果为:
在这里插入图片描述
用Object.is(item, items)比较两个值是否相等

    <script>
        const arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{a: {c: 2, b: 1}},{a: {b: 1, c: 2}}, {}, {}];
        let newArray = [];
        function digui(first, second) {
            const firstList = Object.keys(first);
            const secondList = Object.keys(second);
            let isFlag = false;
            if (firstList.length !== secondList.length) return false;
            if (firstList.length === 0 && secondList.length === 0) return true;
            for (let key1 in first) {
                for (let key2 in second) {
                    if (key1 === key2) {
                        if (Object.prototype.toString.call(first[key1]) === '[object Object]' && Object.prototype.toString.call(second[key2]) === '[object Object]') {
                            // 如果是对象
                            return digui(first[key1], second[key2]);
                        } else {
                            if (first[key1] === second[key2]) {
                                isFlag = true
                            } else {
                                isFlag= false
                            }
                        }
                    }
                }
            }
            return isFlag;
        }
        function unique(arr){
            // const resultList = Array.from(new Set(arr));
            arr.map(item => {
                let result = null;
                newArray.map(items => {
                    if (Object.is(item, items)) {
                        result = true;
                        return;
                    }
                    if (Object.prototype.toString.call(item) === '[object Object]') {
                        // 如果是对象
                        if (Object.prototype.toString.call(item) ===  Object.prototype.toString.call(items)) {
                            result = digui(item, items);
                        }
                    }
                })
                if (!result) {
                    newArray.push(item);
                }
            })
            return newArray;
        }
        console.log(unique(arr));
    </script>

17.实现一个获取对象任意属性值的方法,

比如:
const getAttribute = (object, path, defaultValue) => {
}

const obj = {a: {b: {c: 100}}, d: [{f: ‘abc’}]};

getAttribute(obj, ‘a.b.c’, 0) === 100
getAttribute(obj, ‘a.b.e’, ‘default’) === ‘default’
getAttribute(obj, ‘d.0.f’) === ‘abc’

const getAttribute = (object, path, defaultValue) => {
        const keysList = path.split('.');
        let result = object;
        let value = defaultValue;
        keysList.map(key => {
            if (!isNaN(key)) {
                // 如果是数字
                result = result[Number(key)];
                return;
            }
            if (result[key]?.constructor === Object) {
                result = result[key]
            } else if (result[key]?.constructor === Array) {
                // 如果值是数组
                result = result[key];
            } else {
                if (result[key]) {
                    value = result[key];
                }
            }
        })
        return value;
    }

    const obj = { a: { b: { c: 100 } }, d: [{ f: 'abc' }] };
    console.log(getAttribute(obj, 'a.b.c', 0));
    console.log(getAttribute(obj, 'a.b.e', 'default'));
    console.log(getAttribute(obj, 'd.0.f'));





这个题目遇到两次了,第一次是要求如果有值返回值,没有值返回undefinedconst getAttribute = (object, path) => {
        const keysList = path.split('.');
        let result = object;
        let value = undefined;
        keysList.map(key => {
            if (!isNaN(key)) {
                // 如果是数字
                result = result[Number(key)];
                return;
            }
            if (result[key]?.constructor === Object) {
                result = result[key]
            } else if (result[key]?.constructor === Array) {
                // 如果值是数组
                result = result[key];
            } else {
                if (result[key]) {
                    value = result[key];
                }
            }
        })
        return value;
    }

    const obj = {
        a: {
            aa: {
                aaa: 'rang'
            }
        },
        b: [{}, {}, { bb: 'blue' }]
    };
    console.log(getAttribute(obj, 'a.aa.aaa') === 'rang');  // 返回true
    console.log(getAttribute(obj, 'b.2.bb') === 'blue'); // 返回true
    console.log(typeof getAttribute(obj, 'c.c.cc') === 'undefined'); // 返回true
    console.log(getAttribute(obj, 'a.b.c')); // 返回undefined

18.写一个json格式化代码

参考文章:
https://blog.51cto.com/ohxiaohu/6103652
https://blog.csdn.net/m0_68634366/article/details/129549935
https://blog.51cto.com/u_16175515/6898954

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <textarea rows="10" cols="100" id="inputBox"></textarea>
    <p id="showText" contenteditable="true">
        <pre id="myPre" style="width: 100%;height: 500px;overflow: auto;background-color: white;"></pre>
    </p>
    <!-- <textarea id="showText" rows="15"></textarea> -->

    <script>
        var textarea = document.querySelector('#inputBox')
        textarea.addEventListener('input', function () {
            textarea.style.height = 'auto';
            textarea.style.height = textarea.scrollHeight + 'px';

            // var a = JSON.stringify({ "code": "0", "msg": "查询成功", "resultData": [{ "hhrAddress": "南京市建邺区江东中路228号", "hhrBirthDate": 631123200000 }, { "hhrAddress": "北京京市建邺区江东中路666号", "hhrBirthDate": 1545315245 }], "systemId": "" });
            let newJSON = JSON.stringify(JSON.parse(textarea.value), null, '\t');
            myPre = document.getElementById('myPre');
            myPre.innerText = newJSON
        })
    </script>
</body>

</html>

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值