JS算法

/**
 * @description 数组去重
 * @param {number[]} arr
 */

exports.uniqueByObj = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    // 利用object的属性key不能相同特点来进行筛选
    let hash = {}
    let results = []
    for(let i = 0; i< arr.length; i++) {
        if(!hash[arr[i]]) { //!hash[arr[i] 为 true
            hash[arr[i]] = true
            results.push(arr[i])
        }
    }
    return results
}

exports.uniqueByIndexOf = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    // 数组下标判断法,当值不在新数组时,就加入该数组,如果在就不加了
    let results = []
    for(let i = 0; i < arr.length; i++) {
        if(results.indexOf(arr[i]) === -1) {
            results.push(arr[i])
        }
    }
    return results
}

exports.uniqueByTwoLoop = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    // 优化遍历数组法(推荐) 双层循环,(检测到有重复值时终止当前循环同时进入外层循环的下一轮判断)
    let results=[];
    for (let i = 0; i < arr.length; i++) {
      for (let j = i+1; j < arr.length; j++) {
        if(arr[i] === arr[j]){
          ++i;
        }
      }
      results.push(arr[i]);
    }
    return results;
}

exports.uniqueBySet = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    // ES6中的Set数据结构,类似于数组,它的成员都是唯一的 ,其构造函数可以接受一个数组作为参数
    // ES6中Array新增了一个静态方法Array.from,可以把类似数组的对象转换为数组
    let set = new Set(arr)
    return Array.from(set)
}

exports.uniqueBySetSimple = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    return [...new Set(arr)]
}

exports.uniqueByIncludes = (arr) => {
    if(!Array.isArray(arr)) {
        console.log('type error')
        return
    }
    let results = []
    for(let i=0;i<arr.length;i++) {
        if(!results.includes(arr[i])) { // includes检测数组是否有某个属性值
            results.push(arr[i])
        }
    }
    return results
}
/**
 * @description 数组排序算法, 冒泡排序
 * @param {number[]} arr
 */

 exports.bubbleSort = (arr) => { // 冒泡排序
    for(let i = 0; i < arr.length - 1; i++) {
        for(let j = i+1; j < arr.length; j++) {
            if(arr[i] > arr[j]) { //相邻元素两两对比
                let tem = arr[i] //元素交换
                arr[i] = arr[j]
                arr[j] = tem
            }
        }
    }
    return arr
 }
exports.bubbleSort1 = arr => { // 这种方式比上一种更快 当i=0的时候,里面的循环完整执行,从j=0执行到j=6,这也就是第一遍排序,结果是将最大的数排到了最后
  // 当i=1的时候,里面的循环再次完整执行,由于最大的数已经在最后了,没有必要去比较数组的最后两项,这也是j<arr.length-1-i的巧妙之处
  for(let i = 0; i < arr.length - 1; i++) {
    for(let j = 0; j < arr.length - 1 - i; j++) {
      if(arr[j] > arr[j+1]) {
        let temp = arr[j]
        arr[j] = arr[j+1]
        arr[j+1] = temp
      }
    }
  }
  return arr
}
 /**
 * @description 快速排序, 对冒泡排序的改进
 * @param {number[]} arr
 */
exports.quickSort = (arr) => {
    if(arr.length <= 1) {
        return arr
    }
    let pivotIndex = Math.floor(arr.length / 2)
    let pivot = arr.splice(pivotIndex, 1)[0]
    let left = []
    let right = []
    for(let i=0;i<arr.length;i++) {
        if(arr[i] < pivot) {
            left.push(arr[i])
        } else {
            right.push(arr[i])
        }
    }
    return quickSort(left).concat([pivot],quickSort(right));
}
/**
* @description 选择排序
* @param {number[]} arr
*/
exports.selectSort = arr => {
  let minIndex, temp
  for(let i = 0;i < arr.length - 1; i++) {
    minIndex = i
    for(let j = i + 1; j < arr.length; j++) {
      if(arr[j] < arr[minIndex]) {
        minIndex = j
      }
    }
    temp = arr[i]
    arr[i] = arr[minIndex]
    arr[minIndex] = temp
  }
  return arr
}
/**
 * @description 水仙花数,水仙花数是一种特殊的三位数,它的特点就是,每个数位的立方和,等于它本身
 * @param {number} num
 */

 exports.daffodil = (num) => {
     let results = []
     for(let i=100;i<num;i++) {
        let nUnit = parseInt(i % 10) // 个位
        let nTen = parseInt((i / 10) % 10) // 十位
        let nHundred = parseInt((i / 100) % 10) // 百位
         if(Math.pow(nUnit, 3) + Math.pow(nTen, 3) + Math.pow(nHundred, 3) == i) {
            //  console.log(i)
            results.push(i)
         }
     }
     return results
 }

 /**
  * @description 给定数组,返回的两个数字之和等于目标数字
  * @param {number[]} nums
  * @param {number} target
  * @return {number[]}
  * Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9,return [0, 1].
 */
exports.twoSum =(nums, target) => {
    let low = 0, high = nums.length -1;
    let sum = 0
    while(low < high) {
        sum = nums[low] + nums[high] // 数组两端的数字相加,与目标数字比较
        if(sum > target) { // 如果和大于目标数字,就将数组索引大的减少1
            high --
        } else if (sum < target) { // 如果和小于目标数字,就将数组索引大的加1
            low++
        } else { // 知道等于目标数字,输出此时数组的索引,记得都加1,或者知道索引大的等于索引小的,输出[-1, -1]
            return [low, high]
        }
    }
    return [-1, -1]
};

/**
 * @description 二分查找,非递归算法
 * @param {number[]} arr
 * @param {number} key
 */
// 在有序数组中查找特定元素的搜索算法, 返回目标元素索引值
exports.binarySearch = (arr, key) => {
    if(!contains(key)) {
        return
    }
    let low = 0, high = arr.length - 1
    while(low <= high) {
        let mid = parseInt((high + low) / 2)
        if(key == arr[mid]) {
            return mid
        } else if(key > arr[mid]) {
            low = mid + 1
        } else if(key < arr[mid]) {
            high = mid - 1
        } else {
            return -1
        }
    }
}

/**
 * @description 判断元素是否存在数组中
 * @param {number[]} arr
 * @param {number} obj
 */
const contains = function(arr, obj) {
    let i = arr.length;
    while (i--) {
      if (arr[i] === obj) {
        return true;
      }
    }
    return false;
}

/**
 * @description 阶乘 n! = n*(n-1)...21 , 6! = 6 * 5 * 4 * 3 * 2 *1
 * @param {number} number
 */
const factorial = function(number) {
    if(number == 1) {
        return number
    } else {
        // return number*factorial(number - 1)  or
        return number*arguments.callee(number - 1) // arguments.callee 表示拥有arguments对象的函数
    }
}
/**
 * @description 斐波那契数列
 * @param {number} number
 */
// 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 求第n个数是多少
// 规律:后一项是前两项的和
const fibonacci = function(number) {
    if(number <= 2) {
        return 1
    }
    return fibonacci(number - 1) + fibonacci(number - 2)
}


/*
* 删除数组对象中多个数组元素
* { list } 数组对象 [{},{}]
* { currentSelected } 数组对象 [{},{}]
*/
const updataSearchList = (list, currentSelected) => {
    for(var i = 0;i<list.length;i++) {
        for(let j=0;j<currentSelected.length;j++) {
            if(list[i].contactId === currentSelected[j].contactId) {
                list.splice(i,1);
                i--;
            }
        }
    }
}

// ---------------------你不知道的js-------------------------------------------------------

function process(data) {
// 在这里做点有趣的事情
}
var someReallyBigData = { //.. };
process( someReallyBigData );
var btn = document.getElementById( "my_button" );
btn.addEventListener( "click", function click(evt) {
console.log("button clicked");
}, /*capturingPhase=*/false );

// click 函数形成了一个覆盖整个作用于的闭包,JS引擎极有可能依然保存着 someReallyBigData

/*
* 为变量显式声明块作用域, 就可解决
*/
function process(data) {
// 在这里做点有趣的事情
}
// 在这个块中定义的内容可以销毁了!
{
let someReallyBigData = { //.. };
process( someReallyBigData );
}
var btn = document.getElementById( "my_button" );
btn.addEventListener( "click", function click(evt){
console.log("button clicked");
}, /*capturingPhase=*/false );

/*
  函数声明和变量声明都会被提升 函数会首先被提升,然后才是变量 重复的声明会被忽略
*/



/*
  闭包-----当函数可以记住并访问所在词法作用域时, 就产生了闭包, 即使函数实在当前词法作用域之外
*/
function foo() {
  var a = 2
  function bar() {
    console.log(a)
  }
  return bar

}
foo()(); // 调用内部的bar 朋友 这就是闭包

// 无论以何种方式对函数类型的值进行传递,当函数在别处被调用都可以观察到闭包

function foo() {
  var a = 2
  function baz () {
    console.log(a)
  }
  bar(baz)
}
foo()
function bar(fn) {
  fn(); // 妈妈快看呀,这就是闭包!
}

// 传递函数当然也可以是间接的
var fn
function foo() {
  var a = 1
  function bar() {
    console.log(a)
  }
  fn = bar; // 将baz 分配给全局变量
}

foo()
fn()
/*
  只要使用了回调函数,实际上就是在使用闭包!
*/

// console.log(typeof(null))
/*
  不同的对象在底层都表示为二进制,在JavaScript 中二进制前三位都为0 的话会被判
  断为object 类型,null 的二进制表示是全0,自然前三位也是0,所以执行typeof 时会返回“object”。
*/

/*
  将两级数组平铺成一级
*/
var children = ['a','b',['c','d']]
function toOneLevel(children) {
  for (var i = 0; i < children.length; i++) {
    if (Array.isArray(children[i])) {
      return Array.prototype.concat.apply([], children)
    }
  }
}
// ["a", "b", "c", "d"]

/*
筛选数组对象
a: [{guid: '1'}, {guid: '2'},{guid: '4'}, {guid: '3'}]
b: [{guid: '1'}, {guid: '3'}]
结果: {guid: '2'},{guid: '4'}
*/
var c = a.filter(item => b.map(itemB => {
    return itemB.guid
}).indexOf(item.guid) < 0)

// 如果有不断变化的数字,只取前一个和当前值
let arr = [0, 0] 默认是0
function foo (data) {
  arr. shift() 删掉第一个元素
arr[1] = data
}
/**
 * @description 将数组平铺到指定的深度
 */
const flatten = (arr, depth = 1) => 
    depth != 1 ? arr.reduce((a, v) => a.concat( Array.isArray(v) ? flatten(v, depth - 1) : v), [])
    : arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v) : v), [])
/**
 * @description 将数组扁平化并去重排序
 */
function flatten(arr) {
    const res = arr.reduce((a, v) => a.concat(Array.isArray(v) ? flatten(v) : v), [])
    return Array.from(new Set(res)).sort((a, b) => a - b)
}
或者用 内置的flat(Infinity)平铺数组

/**
 * @description 取整 | 0
 */
const getInt = num => num | 0

// 截取数组,按照给定的数字
function sliceArray (num) {
  let result = []
  for (let i=0;i < arr.length; i++){
    if(i % num === 0) {
        result.push(arr.slice(i, i + num))
    }
  }
}

// 取前一个和当前的元素
let arr = [] // 放在外面
function foo(value) {
  arr.shift()
  arr[1] = value
}

// 创建随机数
  rndId (n) {
      let rnd = ''
      for(let i = 0; i < n; i++)
        rnd += Math.floor(Math.random() * 10)
      return rnd
    },
    /**
     * @description 数字转为字母
     * @param {Number} n 数字
     */
    createCellPos( n ){
      const ordA = 'A'.charCodeAt(0)
      const ordZ = 'Z'.charCodeAt(0)
      const len = ordZ - ordA + 1
      let s = ''
      while( n >= 0 ) {
        s = String.fromCharCode(n % len + ordA) + s
        n = Math.floor(n / len) - 1
      }
      return s
    },

// 数组获取负索引
const negativeArray = els => new Proxy(els, {
  get: (target, k) => Reflect.get(target, +k < 0 ? String(target.length + +k) : k)
})
var arr = negativeArray([1,2,3,4])
arr[-1]

// 打乱数组
function shuffle (arr) {
    let len = arr.length
    let randomIndex = null
    let currentItem = null
    while (len) {
        // 获取最后一个元素之前的随机位置
        randomIndex = Math.floor(Math.random() * len--)
        currentItem = arr[len]
        arr[len] = arr[randomIndex]
        arr[randomIndex] = currentItem
    }
    return arr
}

// 获取url中的参数
  function parseQuery (query) {
    const reg = /([^=&\s]+)[=\s]*([^&\s]*)/g
    let obj = {}
    while (reg.exec(query)) {
      obj[RegExp.$1] = RegExp.$2
    }
    return obj
  }
parseQuery(window.location.search.substr(1))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容