/**
* @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))
JS算法
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...