(本周总结)工具库源码+算法+原生

202快乐数

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1

如果可以变为1,那么这个数就是快乐数

输入: 19
输出: true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
/*和不等于1,且重复就不是快乐树*/
const isHappy = n => {
    let set = new Set()
    n += ''
    let sum = 0
    while (sum != 1) {
        sum = 0
        for (let i = 0; i < n.length; i++) {
            sum += n[i] ** 2
        }
        if (set.has(sum)) return false
        n=sum+''
        set.add(sum)
    }
    return true
}
console.log(isHappy(20))//false

//第二种
const isHappy = n => {
    let exit = []
    let sum
    while (n != 1) {
        sum = 0
        while (n !=0) {
            sum += (n % 10) ** 2
            n = parseInt(String(n / 10))
        }
        if (exit.indexOf(sum) > -1) {
            return false
        }else{
            exit.push(sum)
        }
        n=sum
    }
    return true

}

Leetcode 1137 第 N 个泰波那契数

输入:n = 4
输出:4
T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

const Solution = n => {
  const arr = [0, 1, 1]
  if (n < 3) {
    return arr[n]
  }
  return Solution(n - 3) + Solution(n - 2) + Solution(n - 1)
}
console.log(Solution(5))

const Solution = n => {
  const arr = [0, 1, 1]
  if (n < 3) {
    return arr[n]
  }
  for (let i = 3; i <= n; i++) {
    arr[i] = arr[i - 3] + arr[i - 2] + arr[i - 1]
  }
  return arr[n]
}
console.log(Solution(5))

LeetCode 179 数组拼接为最大数

输入: [10,2]
输出: 210

输入: [3,30,34,5,9]
输出: 9534330

const largesNumber = nums => {
  nums = nums.map(String)
  nums.sort((a, b) => parseInt(b + a) - parseInt(a + b))
  if(nums[0]==0) return '0'
  return nums.join('')
}

LeetCode 200

const numIslands = nums => {
  if (nums.length == 0) return 0;
  let count = 0;
  for (let i = 0; i < nums.length; i++) {
    for (let j = 0; j < nums[0].length; j++) {
      if (nums[i][j] == 1) {
        count++
        helper(i, j, nums)
      }
    }
  }
  return count
}
const helper = (i, j, nums) => {
  if (i < 0 || j < 0 || i >= nums.length || j >= nums[0].length || nums[i][j] != 1) return ;
  nums[i][j] = '*';
  helper(i - 1, j, nums);
  helper(i + 1, j, nums);
  helper(i, j - 1, nums);
  helper(i, j + 1, nums)
}
console.log(numIslands([['1', '0', '1', '1', '1'], ['1', '0', '1', '0', '1'], ['1', '1', '1', '0', '1']]))

198 打家劫舍

相邻两家不能同时闯入

输入: [1,2,3,1]
输出: 4
 1 + 3 = 4 
 
输入: [2,7,9,3,1]
输出: 12
 2 + 9 + 1 = 12 
const rob1 = nums => {
  let a = 0,
    b = 0;
  for (let i = 0; i < nums.length; i++) {
    if (i % 2 == 0) {
      //a += nums[i];
     // a = Math.max(b, a)
      a = Math.max(b, (a + nums[i]))
    } else {
      // b+=nums[i]
      // b=Math.max(a,b) 
      b = Math.max(a, (b + nums[i]))
    }
  }
  return Math.max(a, b)
}

///动态规划

  let n = nums.length;
  if (n <= 1) return n == 0 ? 0 : nums[0];
  let arr = [];
  arr[0] = nums[0];
  arr[1] = nums[1]
  for (let i = 2; i < n; i++) {
    arr[i] = Math.max(arr[i - 1], nums[i] + arr[i - 2]);
  }
  console.log(arr)
  return arr[n - 1]
}

leetCode 191 位1的个数

const hammingh = n => n.toString(2)
  .split('')
  .reduce((acc, val) => (val == '1' && acc++, acc), 0)

leetCode 190 颠倒二进制位

var reverseBits = n => {
  let t = n.toString(2).split('')
  while (t.length < 32) {
    t.unshift('0')
  }
  return parseInt(t.reverse().join(''),2)
};

console.log(reverseBits(100))

leetCode 49

输入: ['abc','acb','bbc','cbb']

输出: [['abc','acb'],['bbc','cbb']]

const GroupAnrgrams = strs => {
  let map = new Map();
  for (let i = 0; i < strs.length; i++) {
    let key=strs[i].split('').sort().join();
    if (!map.has(key)) {
      map.set(key,[strs[i]])
    }else{
      let temp=map.get(key)
      temp.push(strs[i])
      map.set(key,temp)
    }
  }
  return Array.from(map.values())
}
console.log(GroupAnrgrams(['abc', 'bcd', 'mss','bca']))

leetCode 5 最长回文子串

输入: "babad"

输出: "bab"

const Solution = str => {
  let n = str.length;
  let res = ''
  const helper = (i, j) => {
    //查找回文的中心
    while (i >= 0 && j < n && str[i] == str[j]) {
      i -= 1
      j += 1
    }
    //确定好边界
    if (res.length < j - i - 1) {
      res = str.slice(i + 1, j)
    }
  }
  for (let i = 0; i < n; i++) {
    helper(i,i)
    helper(i,i+1)
  }
  return res
}
console.log(Solution('abcbaddd'))


//第二种
//这种for循环看得少
for (let i = 0; i < n; i++) {
    for (let j = i; j >= 0; j--) {}}
n=3
//输出的结果
[ [ 0, 0 ],
  [ 1, 1 ],
  [ 1, 0 ],
  [ 2, 2 ],
  [ 2, 1 ],
  [ 2, 0 ],
  [ 3, 3 ],
  [ 3, 2 ],
  [ 3, 1 ],
  [ 3, 0 ] ]
不好理解,我就不写啦

164. 最大间距

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。

例如

输入: [3,6,9,1]

输出: 3

const maxinum = nums => {
  let n = nums.length;
  let res = 0;
  if (n < 2) {
    return 0
  }
  nums.sort((a,b)=>a-b)
  for (let i = 1; i < n; i++) {
    res = Math.max(res, nums[i] - nums[i - 1])
  }
  return res
}

DOM复习

document.querySelector 返回第一个匹配的Element

document.querySelectorAll 返回的是一个类数组

Array.from(document.querySelectorAll('.aaa'))
  .forEach(val => val.innerHTML = '333');
   [...document.querySelectorAll('.aaa')].map(val=>val.innerHTML='333')

但是上面的这两种性能较差,尽量使用

document.getElementById()
document.getElementsByTagName()

属性查找

 document.querySelector("div[class='bbb']")

后代查找

$el.querySelector('.bbb')

兄弟元素

 let a=document.querySelector('.bbb')
      //我的父节点的所有孩子,除掉自身的所有兄弟节点
     let b=[...a.parentNode.children].filter(val=>val!==a)

上一个元素

el.previousElementSibling;

下一个元素

el.nextElementSibling;

Input/Textarea

document.querySelector('.aaa').value

event

在vue中是在点击或者其实事件传入$event
原生事件委托
 let a=document.querySelector('.aaa')
a.addEventListener('click',(e)=>{
        console.log(e.target) //拿到点击的dom节点
      })

获取属性

el.getAttribute('class')

设置属性

el.setAttribute('属性','值')

添加class

$el.classList.add('aaaa')

删除class

$el.classList.remove('aaa')

has class

$el.classList.contains('aaa')

toggle class

$el.classList.toggle('aaa')

offset 偏移

offsetWidth和offsetHight 获取节点的宽度和高度

offset宽/高  =  盒子自身的宽/高 + padding+border;
`offsetWidth` =width+padding+border;
`offsetHeight` =Height+padding+border;

offsetLeft和offsetTop (检测距离父盒子有定位的左/上面的距离)

offsetParent (检测父系盒子中带有定位的父盒子节点)

区别

offsetTop返回的是只读的,且返回的是数字

scroll

scrollTop
scrollLeft

Rambda工具库源码学习

curry() 这个很经典放前面

curry((a,b,c)=>a+b+c)(1,2,3) //6
curry((a,b,c)=>a+b+c)(1)(2)(3) //6

const curry = (fn, args = []) =>
  (..._args) => (rest => rest.length >= fn.length ? fn(...rest) : curry(fn, rest))([...args, ..._args])

const curry = (fn, ...args) =>
  fn.length <= args.length ? fn(...args) : curry.bind(null, fn, ...args);

好懂版
const curry = (fn, ...args) => (..._args) => (test => test.length < fn.length ? curry(fn, ...test) : fn(...test))([...args, ..._args])

const curry = (fn, ...args) => {
  if (args.length<fn.length) {
    return curry.bind(null, fn, ...args)
  }
  return fn(...args)
}

add()

add(1,2) //3
add(1)(2) //3

function add(a, b) {
  if (arguments.length == 1) {
    return _=>add(a,_)
  }
  return a+b;
}

adjust()

adjust(val=>val+1,1,[1,2,3])// [1,3,3]
const adjustRaw = (fn, idx, list) => {
  const clone = list.slice()
  const Index = list.length > 0 ? idx : list.length - idx;
  clone[Index] = fn(clone[Index])
  return clone
}

all()

all(v => v > -1, [1, 1, 1, 1, -1])// false
all(val=>val==2)([2, 2, 2, 2,]) //true

function all(fn, list) {
  if (arguments.length == 1) return _ => all(fn, _)
  return list.every(fn)
}

allPass

const input = {
  a: 1,
  b: 2,
}
const rules = [
  x => x.a === 1,
  x => x.b === 2,
]
allPass(rules, input) //true
allPass(rules)(input)//true

function allPass(fnArray, obj) {
  if (arguments.length == 1) return _ => allPass(fnArray, _);
  return fnArray.some(fn => fn(obj))
}

always

const always = val => () => val
always(3)() //3

defaultTo

如果第二个参数不是 nullundefinedNaN

则返回第二个参数,否则返回第一个参数(默认值)

defaultTo(300)(undefined/null/NaN)  //300
defaultTo(300)(30) //30
defaultTo(300,undefined,null,3) //30

const flag = s => s == undefined || Object.is(s, NaN)

function defaultTo(a, ...b) {
  if (arguments.length == 1) {
    return _ => defaultTo(a, _)
  }
  if (arguments.length == 2) {
    return flag(b[0]) ? a : b[0]
  }
  let i = 0;
  while (i < b.length) {
    if (!flag(b[i])) {
      return b[i]
    }
    i++
  }
  return a
}

dissoc()

dissoc('b', {a: 1, b: 2, c: 3}); //=> {a: 1, c: 3}

function dissoc(prop, obj) {
  if (arguments.length == 1) {
    return _ => dissoc(prop, _)
  }
  if (obj == undefined || obj == null) {
    return {}
  }
  let a = Object.assign({}, obj)
  delete a[prop]
  return a
}

equals

const type = val => {
  if (typeof val == 'number') {
    return isNaN(val) ? 'NaN' : 'number'
  } else {
    return Object.prototype.toString.call(val)
      .split(' ')[1].slice(0, -1)
  }
}

function equals(a, b) {
  if (arguments.length == 1) {
    return _ => equals(a, _)
  }
  if (a === b) {
    return true
  }
  if (type(a) !== type(b)) {
    return false
  }
  if (type(a) == 'Array') {
    let aArray = a.concat()
    let bArray = b.concat()
    if (aArray.toString() !== bArray.toString()) {
      return false
    }
    let flag = true;
    aArray.forEach((val, index) => {
      if (flag) {
        if (val != bArray[index] && !equals(val, bArray[index])) {
          flag = false
        }
      }
    })
    return flag;
  }
  if (type(a) == 'Object') {
    const aKeys = Object.keys(a)
    if (aKeys.length !== Object.keys(b).length) {
      return false
    }
    let flag = true;
    aKeys.map(val => {
      if (flag) {
        const aValue = a[val];
        const bValue = b[val];
        if (aValue !== bValue && !equals(aValue, bValue)) {
          flag = false
        }
      }
    })
    return flag
  }  
  return false
}

lodash源码深入

after()

调用多少次后才执行

const after = (n, func) => {
  return (...args) => {
    if (--n < 1) {
      return func.apply(null, args)
    }
  }
}

**例子**
let f = after(2, (a, b) => {
  return a + b
})
console.log(f(2, 3)) //undefined
console.log(f(2, 3))  //5   

before(n,func)

调用不超过n次

const before = (n, func) => {
  return (...args) => {
    if (n-- > 0) {
      return func.apply(null, args)
    }
      func=undefined
  }
}
let a=before(2,(a,b)=>a+b)
console.log(a(1, 2)) //3
console.log(a(1, 2)) //3
console.log(a(1, 2)) //undefined

sum(array)

const sums = array => {
  let result = 0;
  if (array != null && array.length) {
    for (let item of array) {
      result += item
    }
  }
  return result
}

pull(array,...args)

**例子**
let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];
pull(myArray, 'a', 'c'); // myArray = [ 'b', 'b' ]   

const pull = (arr, ...args) => {
  let pulled = arr.filter(val => !args.includes(val))
  //删除原有数组的元素
  arr.length = 0
  pulled.forEach(val => arr.push(val))
};
let arr = [1, 2, 3, 4, 5]
pull(arr, 1, 2)
console.log(arr)

uuid(a,b)

UUID 是 通用唯一识别码

function uuid(a, b) {
  for (
    b = a = ''; a++ < 36;
    b += a * 51 & 52 ?
      (a ^ 15 ? 8 ^ Math.random() * (a ^ 20 ? 16 : 4) : 4).toString(16)
      : '-') ;
  return b
}
console.log(uuid(2, 3))
//4f656637-ea34-4a16-a4b0-31872ab177da

这种位运算我这种级别还看不懂,先写上去

deepClone()

const deepClone = obj => {
  let clone = Object.assign({}, obj)
  Object.keys(clone)
    .forEach(val => {
      clone[val] = typeof obj[val] == 'object' ? deepClone(obj[val]) : obj[val]
    })
  if (Array.isArray(obj) && obj.length) {
    return (clone.length = obj.length) && Array.from(clone)
  } else {
    return Array.isArray(obj) ? Array.from(obj) : clone
  }
}

mb()

//要查找的对象
var obj1 = {
  a: {
    b: [{ hello: 'world' }]
  }
};
//要查找的条件
const arr = ['a', 'b', 0, 'hello']
console.log(a(arr)(obj1))
//world
const mb=p=>obj=>p.map(val=>obj=(obj||{})[val])&&obj

qart

给二维码添加背景

自执行函数

void function() {
  console.log(0)
}()
+function(){
  console.log(1)
}()
-function(){
  console.log(2)
}()
~function(){
  console.log(3)
}();
!function(){
  console.log(4)
}();
(function(){
  console.log(5)
})()

对象成员

const obj={
  name:'zhangsan',
  age:12,
  method(){
      return 2
  }  
}
for (let item in obj) {
  console.log(item)  //打印键
}

使用对象成员的`.`  `[]`
"." 和"[]" 都是对象成员存取运算符,所不同的是:
前面右边的运算元必须是一个标识符,后面中间的运算元可以是变量,直接量或表达式
obj.name
obj['name']

obj.method()
obj.['method']()
posted @ 2019-08-09 17:34  猫神甜辣酱  阅读(356)  评论(0编辑  收藏  举报