Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说JavaScript算法(数组,字符串...)「建议收藏」,希望能够帮助你!!!。
数组的排序和去重,一直是面试中的一个热点,一般是要求手写数组去重方法的代码,因为它能够很好地考察一个人的逻辑思维能力。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看。这些知识只要经过一定地刻意训练,多看,多思考,多敲代码,这些算法的掌握其实是一件很简单的事情。
全文分为两部分,数组的排序 和 数组的去重。
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];//定义一个空的数组
for (var i = 0; i < arr.length; i++) {
if (array .indexOf(arr[i]) === -1) {//判断数组中是否有arr[i]这个元素
array .push(arr[i])
}
}
return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重
新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。
方法一:
双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]
//NaN和{}没有去重,两个null直接消失了
方法二:
var arr=[11,22,33,44,55,22,33,54];
for(var n=0;n<arr.length;n++){
if (arr.indexOf(arr[n])!=arr.lastIndexOf(arr[n])){
//判断arr[n]出现的次数,如果次数不是一次,那么删除后边的元素
arr.splice(arr.lastIndexOf(arr[n]),1);
n--;//没有这个n--,相当于执行了8次,
}
}
console.log(arr);
function unique (arr) {
return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return;
}
arr = arr.sort()
var arrry= [arr[0]];
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== arr[i-1]) {
arrry.push(arr[i]);
}
}
return arrry;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]
//NaN、{}没有去重
利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var arrry= [];
var obj = {};
for (var i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
arrry.push(arr[i])
obj[arr[i]] = 1
} else {
obj[arr[i]]++
}
}
return arrry;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, null, NaN, 0, "a", {…}]
//两个true直接去掉了,NaN和{}去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array =[];
for(var i = 0; i < arr.length; i++) {
if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
array.push(arr[i]);
}
}
return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
//{}没有去重
function unique(arr) {
var obj = {};
return arr.filter(function(item, index, arr){
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]
//所有的都去重了
利用hasOwnProperty 判断是否存在对象属性
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
function unique(arr) {
var array= arr;
var len = array.length;
array.sort(function(a,b){ //排序后更加方便去重
return a - b;
})
function loop(index){
if(index >= 1){
if(array[index] === array[index-1]){
array.splice(index,1);
}
loop(index - 1); //递归loop,然后数组去重
}
}
loop(len-1);
return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]
function arrayNonRepeatfy(arr) {
let map = new Map();
let array = new Array(); // 数组用于返回结果
for (let i = 0; i < arr.length; i++) {
if(map .has(arr[i])) { // 如果有该key值
map .set(arr[i], true);
} else {
map .set(arr[i], false); // 如果没有该key值
array .push(arr[i]);
}
}
return array ;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]
创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。
function unique(arr){
return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
[...new Set(arr)]
//代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码)
综合拓展:多维数组化为一维数组,然后进行去重,升序,
方法1:
function f (arr) {
if (Object.prototype.toString.call(arr) !='[object Array]') {//判断是否为数组
return;
}
var newarr = [];
function fn (arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].length) {
fn(arr[i]);
}else{
newarr.push(arr[i]);
}
}
}
fn(arr);
return newarr;
}
Array.prototype.u = function () {//去重
var newarr = [];
var obj = {};
for (var i = 0; i < this.length; i++) {
if (!obj[this[i]]) {
newarr.push(this[i]);
obj[this[i]] = 1;
}
}
return newarr;
}
function compare (c1,c2) {//排序
return c1 -c2;
}
var arr = [2, -5, 6, [6, -5, [2, 5], [8, 10, [6, 8], -3], 2], 5]
var a = [];
a = f(arr);
b = a.u();
c = b.sort(compare);
console.log(c);
方法2:
Array.prototype.flat= function() {
return [].concat(...this.map(item => (Array.isArray(item) ? item.flat() :
[item])));
}
Array.prototype.unique = function() {
return [...new Set(this)]
}
const sort = (a, b) => a - b;
console.log(arr.flat().unique().sort(sort));
方法3:
function spreadArr(arr=[]){
if(arr.some(ele=>Array.isArray(ele))){
let newArr = [];
arr.forEach((ele) => {
if(Array.isArray(ele)){
newArr = newArr.concat(...ele)
}else{
if(!newArr.includes(ele))
newArr.push(ele)
}
})
return spreadArr(newArr);
}
return arr.sort((a,b)=> a-b);
}
spreadArr([ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]);
方法4:
var arr = [2, -5, 6, [6, -5, [2, 5], [8, 10, [6, 8], -3], 2], 5];
function f (arr) {
var newarr = [];
function fn (arr) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].length) {
if (Array.isArray(arr[i])) { //加这步判定的目的是,判断这个元素是否为数组
fn(arr[i]);
} else {
newarr.push(arr[i]);
}else{
newarr.push(arr[i]);
}
}
}
fn(arr);
return newarr;
}
var x = f(arr);
var newarr = [];
for(var n = 0;n < x.length; n++) {
if (newarr.indexOf(x[n]) == -1) {
newarr.push(x[n]);
}
}
newarr.sort((a, b) => a - b)
console.log(newarr)
方法5:
评论区一位朋友提出的方法,我觉得思路也很好,多维数组化为一维数组,
var arr = [12, 23, 34, [6, [6], [6,[7,[8]]]], [5,[5]], [4, [7]], [4, [[3]]], 45, 6];
arr.toString().split(',').map(Number);
//[12, 23, 34, 6, 6, 6, 7, 8, 5, 5, 4, 7, 4, 3, 45, 6]
这但是如果内部有汉字(或者别的字符串)的话,就不能化为纯数字,建议使用前文的算法类方法。
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列5,4,3,2,1或3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
function IsPopOrder(pushV,popV){
if(pushV.length === 0) return false;
var stack = []; // 模拟栈
for(var i = 0, j = 0; i < pushV.length;){
stack.push(pushV[i]);
i += 1;
// 压入栈的值需要被弹出
while(j < popV.length && stack[stack.length-1] === popV[j]){
stack.pop();
j++;
if(stack.length === 0) break;
}
}
return stack.length === 0;
}
思路:
A
添加数据。B
为空,循环将栈A
中内容弹出放入栈B
,并弹出栈B
最后一项B
不为空,则直接弹出栈B
的最后一项ar stackA = [];
var stackB = [];
function push(node){
stackA.push(node);
}
function pop(){
if(!stackB.length){
while(stackA.length){
stackB.push(stackA.pop());
}
}
return stackB.pop();
}
在一个字符串中找出连续的不重复的最大长度的字符串,解决这类问题的思路:
// 连续最长不重复字符串
function getMaxLenStr(str) {
var cur = [];
var maxLenStr = '';
for(var i = 0; i < str.length; i++) {
if(!cur.includes(str[i])) {
cur.push(str[i]);
} else {
cur = []; // 置为空
cur.push(str[i]);
}
// 存储最大长度的字符串
if(maxLenStr.length < cur.length) {
maxLenStr = cur.join('');
}
}
return maxLenStr;
}
getMaxLenStr('ababcabcde'); // abcde
方法二:
var str = "aababcabcdeabcdefaababc";
var x = str.split('').reduce((a, b, index) => {
if(a.indexOf(b) !== -1) {
return a;
}
a.push(b);
return a;
}, []).join('');
console.log(x)
方法三:
var s = "aababcabcdeabcdefaababc";
var lengthOfLongestSubstring = function(s) {
var str = ""; // 用于存放无重复字符串
var arr = [];
for(var i = 0; i < s.length; i++) {
var char = s.charAt(i);
var index = str.indexOf(char);
if(index === -1) {
str += char;
arr.push(str);
} else {
str = str.substr(index + 1) + char;
}
}
return arr.reduce((a, b) => {
return b.length > a.length ? b : a;
}, '');
};
console.log(lengthOfLongestSubstring(s));
function FindGreatestSumOfSubArray(arr) {
let sum = arr[0];
let max = arr[0];
for(let i = 1; i < arr.length; i++) {
if(sum < 0) {
sum = arr[i];
}else{
sum += arr[i];
}
// 记录最大值
if(max < sum) {
max = sum;
}
}
return max;
}
编码规则:coount[letter]
,将letter
的内容count
次输出,count
是0
或正整数,letter
是区分大小写的纯字母。
实例:
const s= 3[a]2[bc]; decodeString(s);
// 返回'aaabcbc'
const s= 3[a2[c]]; decodeString(s);
// 返回 'accaccacc'
const s= 2[ab]3[cd]ef; decodeString(s);
// 返回 'ababcdcdcdef'
思路: 使用栈这种数据结构,如果 push
的内容为‘]’,则循环 pop
字符,直到碰到 ’[‘,然后将pop
出来的字符串按规则整理后,重新 push
进栈中,最后将栈内的内容拼接成字符串输出即可。
方法1:
function decodeString(str) {
let stack = []; // 存储字符串的栈
for (let i = 0; i < str.length; i++) {
let cur = str[i];
if (cur !== ']') {
stack.push(cur);
} else { // 弹出
let count = 0;
let loopStr = [];
let popStr = '';
while ((popStr = stack.pop()) !== '[') {
loopStr.unshift(popStr);
}
count = stack.pop();
// 添加结果
let item = '';
for (let i = 0; i < count; i++) {
item += loopStr.join('');
}
stack.push(...(item.split('')));
}
}
return stack.join('');
}
方法2:
const str = '3[a]2[bc]';
function decodeString(str) {
let Counts = str.split(/\[[a-zA-Z]+\]/);
let Letters = str.match(/[a-zA-Z]+/g);
let newString = "";
Letters.forEach((item,index)=>{
for (var n=0;n<Counts[index];n++) {
newString += item;
}
})
return newString;
}
console.log(decodeString(str))
例如:
deleteNth((1, 1 1, 1), 2); //return [1, 1]
deleteNth((20, 37, 34, 20, 20, 37), 2); //return [20, 37, 34, 20, 37];
方法1:
var arr = [4, 4, 4, 4, 3, 3, 3, 3, 1, 2, 4, 3, 90];
function deleteNth(arr, n) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) == -1) {
newArr.push(arr[i]);
}
}
for (var i = 0; i < newArr.length; i++) {
var sum = 0;
for (var j = 0; j < arr.length; j++) {
if (arr[j] == newArr[i]) {
sum ++;
if (sum > n) {
arr.splice(j, 1);
j--;
}
}
}
}
return arr;
}
console.log(deleteNth(arr, 2))
方法2:
var arr = [1, 1, 2, 5, 23, 23, 1, 1];
function deleteNth(arr, n) {
let newArr = arr.map( item => {
return item;
})//原始数据副本
let newArr1 = [];//处理后的数据
for (var i = 0; i < newArr.length; i++) {
if (newArr1.indexOf(newArr[i]) < 0) {
newArr1.push(newArr[i]);
} else if (newArr1.indexOf(newArr[i]) > -1) {
let hasIndexArr = [];//用于存放相匹配的项的索引
for (let j = 0; j < newArr1.length; j++) {
if (newArr1[j] == newArr[i]) {//将匹配的项的索引扔进hasIndexArr
hasIndexArr.push(j);
}
}
if (hasIndexArr.length < n) {//如果数量还不满足n,扔进去
newArr1.push(newArr[i]);
}//如果数量已经满足,则跳过
}
}
return newArr1;
}
console.log(deleteNth(arr,1))
方法3:
var arr = [4, 4, 4, 4, 3, 3, 3, 3, 1, 2, 4, 3, 90];
var cache = {};
function deleteNth(arr, x) {
return arr.filter(function (n) {
cache[n] = (cache[n]||0) + 1;
return cache[n] <= x;
})
}
console.log(deleteNth(arr, 1))
[1, 2, 3, 4, 3, 2, 1] => 返回下标3
[1, 100, 50, -51, 1, 1] => 返回下标1
方法1:
var arr = [1, 2, 3, 4, 3, 2, 1];
function find (arr) {
var sum1 = 0;
for (var i = 0 ; i < arr.length ; i ++) {
sum1 += arr[i];
var sum2 = 0;
for (var j = i + 2 ; j < arr.length ; j ++) {
sum2 += arr[j];
}
if (sum1 == sum2) {
return i + 1;
} else if (i == arr.length - 3 && sum1 !== sum2) {
return "该值不存在";
}
}
}
console.log(find(arr))
方法2:
var arr = [1, 2, 3, 4, 3, 2, 1];
for (var i = 0 ; i < arr.length - 2 ; i ++) {
var arr1 = arr.slice(0, i+1);
var arr2 = arr.slice(i+2);
var sum1 = sum2 = 0;
for (var m = 0 ; m < arr1.length ; m ++) {
sum1 += arr1[m];
}
for (var n = 0 ; n < arr2.length ; n ++) {
sum2 += arr2[n];
}
if (sum1 == sum2) {
console.log(i + 1);
break;
} else if (i == arr.length - 3 && sum1 !== sum2) {
console.log("该值不存在");
}
}
var content = document.querySelector('.content');
// 自定义事件
var evt = new Event('custom');
var customEvt = new CustomEvent('customEvt', {
// 通过这个属性传递参数
detail: {
name: 'tom',
age: 12
}
});
content.addEventListener('custom', (e) => {
console.log('自定义事件被触发,无参数...');
console.log(e);
});
content.addEventListener('customEvt', (e) => {
console.log('自定义事件被触发,有参数...');
console.log(e);
console.log(e.detail);
});
// 点击时触发这个自定义事件
content.addEventListener('click', (e) => {
content.dispatchEvent(evt);
content.dispatchEvent(customEvt);
});
(1)简单数组的简单排序
var arrSimple=new Array(1,8,7,6);
arrSimple.sort();
console.log(arrSimple.join()) ;
(2)简单数组的自定义排序
var arrSimple2=new Array(1,8,7,6);
arrSimple2.sort(function(a,b){
return a-b
});
console.log(arrSimple2.join())
(3)简单对象 List 自定义属性排序
var objectList = new Array();
function Persion(name,age){
this.name=name;
this.age=age;
}
objectList.push(new Persion('jack',20));
objectList.push(new Persion('tony',25));
objectList.push(new Persion('stone',26));
objectList.push(new Persion('mandy',23));
//按年龄从小到大排序
objectList.sort(function(a,b){
return a.age-b.age
});
for(var i=0;i<objectList.length;i++){
document.writeln('<br />age:'+objectList[i].age+' name:'+objectList[i].name);
}
var objectList2 = new Array();
function WorkMate(name,age){
this.name=name;
var _age=age;
this.age=function(){
if(!arguments){
_age=arguments[0];
}else{
return _age;
}
}
}
objectList2.push(new WorkMate('jack',20));
objectList2.push(new WorkMate('tony',25));
objectList2.push(new WorkMate('stone',26));
objectList2.push(new WorkMate('mandy',23));
//按年龄从小到大排序
objectList2.sort(function(a,b){
return a.age()-b.age();
});
for(var i=0;i<objectList2.length;i++){
document.writeln('<br />age:'+objectList2[i].age()+' name:'+objectList2[i].name);
}
十大经典排序算法(Python版本 和 JavaScript版本)
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。