前端中的简单编程题-数组(2)

一边学习前端,一边通过博客的形式自己总结一些东西,当然也希望帮助一些和我一样开始学前端的小伙伴。

如果出现错误,请在评论中指出,我也好自己纠正自己的错误

此文是连接我之前的一篇总结文章,可以去我主页搜索

author: thomaszhou

一到多维数组的最值求解

  • 1.6.1 一维数组的最值
  • for循环或者foreach(比for快点)

    • 不讨论for放啊
  • forEach方法

<script>
//forEach比普通循环效率高点
    var arr = [1,23,45,66,75,111,4];
    Array.prototype.max = function () {
      var max = this[0];
      this.forEach (function (eval) {
        if (eval > max) {
          max = eval;
        }
      });
        return max;
    }
    console.log(arr.max());//111
</script>
复制代码
  • reduce方法来求解
<script>
//reduce()方法
    Array.prototype.max = function () {
      var max = this[0];
      return this.reduce(function (preValue, curValue) {
//        prevalue是每次迭代的结果
        return preValue > curValue ? preValue : curValue;
      })
    }
    console.log(arr.max());
复制代码
  • 用内置函数Math.max()和Math.min()
    • 该方法默认不能直接传一个数组对象作为参数
    var arr = [1,23,45,66,75,111,4];
//    内置函数Math.max()和Math.min()的括号里面不能放数组对象,而是必须放具体的值,如下:
    console.log(Math.max(arr));//NaN
    console.log(Math.max(1,2,43,5,6,777));//77
    console.log(Math.min(1,2,43,5,6,777));//1
    console.log(Math.max());//没有参数的时候,-Infinity
复制代码

以下方法使用来解决不能传递对象参数的问题!

如何解决???
//    需要利用别的方法来引用数组对象
//法一:Function.prototype.apply()

    console.log(Math.max.apply(Math, arr));//111

法二:
    Array.prototype.max = function () {
      return Math.max.apply(Math, arr)
      //return Math.max.apply({}, arr)这个同上条语句
      //不明白为什么是{}??
    }
    console.log(arr.max());//111
复制代码

法三:ES6方法

//    es6的方法-----...展开运算符
//使数组中的值在函数调用的位置展开
const arrayMax = arr => Math.max(...arr);//最大值
const arrayMin = arr => Math.min(...arr);//最小值

console.log(arrMax(arr));//111
</script>
复制代码
  • 1.6.2二维数组的最值

双层for循环是最简单的方法,

  • 比较好的思路是
    • step1:先得出每个子数组的最大值
    • step2:然后找出这些数的最大值
  • 方法一(map,reduce,Math.max()):
var arr2 = [[1,20,5],[3,45,564],[34,12]];
var newMap1 = arr2.map(function (item) {
//map是遍历最外层,item就是每个子数组
      return item.reduce(function (preVal, curVal) {
  //对每个子数组item进行求出最值的操作,并返回
        return preVal > curVal ? preVal: curVal;
      })
    });

console.log(newMap1);//[20,564,34]
//Math.max求出最值
console.log(Math.max(...newMap1));//564
复制代码
  • step1: 在外层数组中使用Array.prototype.map()方法遍历数组。

  • step2: 使用map()方法遍历数组,会调用一个回调函数,在这个回调函数中, 使用reduce()方法对每个子数组group进行合并,将值返回到一个新数组中。

  • step3: 而在使用reduce()方法时,同样会调用一个回调函数,这个回调函数只做了一件事情, 就是子数组中的元素做为比较,如果curVal大于preVal,将会返回current, 否则返回prev,最终得到每个子数组中最大值

  • 方法二(最佳)---目前没看懂

var arr2 = [[1,20,5],[3,45,564],[34,12]];
    function largestOfFour (arr) {
      return arr.map(Function.apply.bind(Math.max, null));
    }
console.log(largestOfFour(arr2)); //[20, 564, 34]
复制代码

这个方案,使用Function.bind方法创建一个特殊的回调函数,就类似于Math.max方法一样,但其有一个Function.prototype.apply功能,将数组作为它的参数。

  • 先对主数组中的每个元素做遍历,也就是数组内部的每个子数组

  • 使用map()方法需要一个回调函数,用来找出内部每个数组中的最大值。需要创建一个函数,让Math.max能接受输入的数组工作。换句话说,这是非常简单而且这样工作也非常的好,如Math.max([9,43,20,6]);将会返回最大值43

  • Function.prototype.apply方法工作可以接受数组做为参数,但函数通过调用上下文,这事情就有点复杂。例如Math.max.apply(null,[9,43,20,6])将调用一个Max.max方法,但这样的方法找起来不容易。

  • 这里给Function.prototype.apply方法传递了一个null参数,告诉Math.max不需要任何上下文。

  • 因为arr.map()需要一个回调函数,而不只是一个表达式,我们在Function.bind方法中提供了一个函数

  • 因为Function.prototype.apply是一个静态方法,类似一个函数对象,我们可以称之为Function.prototype.apply上绑定了一个Function.prototype.bind。例如: Function.apply.bind

  • 现在可以通过Function.prototype.apply.bind回调函数指定其上下文,比如在这个示例中的Math.max方法

  • 由于是嵌入到Function.prototype.apply方法,需要一个上下文作为第一个参数,而且这个上下文还是一个虚假的。

  • 所以我们将null作为第二个参数传递给Function.prototype.apply.bind,并且绑定一个上下文,这个上下文就是Math.max方法

  • 由于Math.max是独立于任何上下文的,所以它会忽略Function.prototype.apply方法调用的虚假上下文

  • 我们使用Function.prototype.apply.bind(Math.max,null)让一个新函数接受arr.map值,比如数组中的子数组

  • 很巧妙的方法!!!!!!!!也是多位数组的方法

 var arr2 = [[1,20,5],[3,45,564],[34,12]];
    var new1 = function (arr) {
//      通过join先把数组里面的值用,拼接成字符串
//        用split将字符串拼接为数组
      return arr.join(',').split(',');
    }(arr2)
//    console.log(largestOfFour(arr2));
    console.log(Math.max(...new1));//564
复制代码
  • 1.3.3 多维数组最值

上文使用不同的方法实现了从二维数组中取出子数组中最大值,并且将这些最大值重新组成一个新数组,如果延伸一下,取出里面的最大值时,还需要使用Array.prototype.max函数,函数中通过Math.max.apply({},this)取得最大值。不过如果不是二维数组,那上述方法将无法取出数组中最大的值。

  • 而在多维数组中取最大值,可以通过join()和split()方法组合在一起:
 var arr2 = [333,[3,45,564],[34,12,[1,4000]]];
    var new1 = function (arr) {
//      通过join先把数组里面的值用,拼接成字符串
//        用split将字符串拼接为数组
      return arr.join(',').split(',');
    }(arr2)
//    console.log(largestOfFour(arr2));
    console.log(Math.max(...new1));//4000
复制代码

数组内部元素随机排列

var arr = [1,2,3,4,5,7,8,9]
arr.sort(function () {
return Math.random() - 0.5
})
复制代码

计数数组中值的出现次数

数组平均数(其实就是数组求和)

使用reduce()将每个值添加到累加器,初始值为0,总和除以数组长度。

const average = arr => arr.reduce((pre, cur) => pre + cur, 0) / arr.length;

// 箭头函数,如果函数只有一条语句,不要加"{}"";"
// average([1,2,3]) -> 2
复制代码
计数数组中值的出现次数

每次遇到数组中的特定值时,使用reduce()来递增计数器。

const arrayCount = (arr, value) => {
  let count = 0;
  arr.forEach(val => {
    val === value? count += 1: count += 0;
	});
  return count;
}
console.log(arrayCount([1,1,2,3,4], 1)); // 2
复制代码

或者reduce方法

const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);

// countOccurrences([1,1,2,1,2,3], 1) -> 3
复制代码

找出数组间不同项-相同项

找出数组a中除数组b以外的值

从b创建一个Set,然后在a上使用Array.filter(),只保留b中不包含的值。

es6: Set结构的has方法,是用来查找值的

const difference = (a, b) => {
	  let s = new Set(b);
	  return a.filter(x => !s.has(x));
	}
   console.log(difference([1,2,3], [1,2]));//[3]
复制代码
找出数组间不同项-相同项(或者说交集)

上面是 !s.has(x)),如果改成s.has(x)),那就是求数组a中和数组b的交集

const difference = (a, b) => {
    let s = new Set(b);
    return a.filter(x => s.has(x));//将!去掉了
  }
  console.log(difference([1,2,3,2], [1,2,4,2]));//[1, 2, 2]
复制代码

过滤数组中的非唯一值

6. 数组去重、合并数组去重(和11相似)

  • 将Array.filter()用于仅包含唯一值的数组。
  • 思路:indexOf和lastIndexOf找的位置相同,那就是唯一的值
const arrayIntersection = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));

// console.log(arrayIntersection([1,2,2,3,4,4,5])); // [1,3,5]
复制代码

数组合并

const arrayConcat = (arr, ...args) => {
    let array = arr.concat(...args);
    return array;
};

console.log(arrayConcat([1], [2,6], 5, [[2],10])); // [1, 2, 6, 5, [2], 10]
复制代码

缺点:只能将二维数组降成一维,如上面[2]就是二维数组

这就联系到深度展开数组的操作,看下面的flatten深度展开数组


flatten深度展开数组

其实就是数组降维:将嵌套多层的数组(嵌套可以是任何层数)转换为只有一层的数组

  • 方法一:
let arr = [1,[2],[[[3,[10]],4],5]];
	let newArr = [];
  function changeArr(arr){
    for(var i=0;i<arr.length;i++){
      //遍历arr数组得每一个元素,这里也可以用forEach
      if(arr[i] instanceof Array){
        //判断元素是否为数组
        changeArr(arr[i])
        //元素为数组则继续调用changeArr方法遍历
      }else{
        newArr.push(arr[i])
        //元素不是数组则可以直接push进新数组
      }
    }
    //此上的判断也可以直接用三元表达式
  }
  changeArr(arr);
  console.log(newArr); //  [1, 2, 3, 10, 4, 5]
复制代码
  • 方法2(可多维):指定降维层数

使用递归去递减深度。使用 Array.reduce() 和 Array.concat() 来合并元素或数组。基本情况下,当深度为 1 时停止递归。省略第二个参数,展开深度为 1。

const flattenDepth = (arr, depth = 1) =>
  depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
  : arr.reduce((a, v) => a.concat(v), []);
  
// 降2维
console.log(flattenDepth([1,[2],[[[3],4],5]], 2)); // [1,2,[3],4,5]
// 降3维
console.log(flattenDepth([1,[2],[[[3],4],5]], 3)); //  [1, 2, 3, 4, 5]
复制代码
  • 方法3(可高维):缺点是得到的值变成了字符形式

数组中元素仅基本类型的元素或数组,可以转换为字符串,不存在循环引用的情况。

function flatten(arr) { return arr.toString().split(',')} 
// arr.toString() 结果是字符串形式的1,2,3,4

<!--// 变成字符形式的数组-->
console.log(flatten([1,[2],[[3]], [[[4]]]])) //["1", "2", "3", "4"]
复制代码

解决办法:最后再遍历一遍数组,用Number转化为数字!


获得第n个斐波那契数字

斐波那契数列是0、1、1、2、3、5、8、13、21、34...

  • 思路:构建一个长度为n的斐波那契数列,然后将最后一个值返回
这个是迭代方式,递归方法太耗时

	function fibonacci(n) {
	  let fibo = [0, 1];
	  if (n < 2) {
	    return n;
		}
	  for (let i = 2; i <= n; i++) {
	    fibo.push(fibo[i-1] + fibo[i-2]);
		}
		return fibo[n];
	}
	console.log(fibonacci(0)); // 0
	console.log(fibonacci(1)); // 1
	console.log(fibonacci(6)); // 8
复制代码

一些简单的应用

数组去掉最后n个值

其实就是去掉最后n个值,利用arr.slice(0,-1)。以0为起点,去一个是-1,去两个是-2,以此类推,

const initial = arr => arr.slice(0, -1);

// initial([1,2,3]) -> [1,2]
复制代码
用值初始化数组

使用Array(n)创建所需长度的数组,fill(v)以填充所需的值,可以忽略value使用默认值0。

const initializeArray = (n, value = 0) => Array(n).fill(value);

// initializeArray(5, 2) -> [2,2,2,2,2]
复制代码
Initialize array with range (使用指定范围来定义数组)

使用 Array(end-start) 创建一个所需长度的数组,使用 Array.map() 来填充范围中的所需值。 你可以省略start,默认值为 0。

const initializeArrayRange = (end, start = 0) =>
  Array.apply(null, Array(end - start)).map((v, i) => i + start);
// initializeArrayRange(5) -> [0,1,2,3,4]
复制代码
数组的最后

返回arr.slice(-1)[0]

const last = arr => arr.slice(-1)[0];
//arr.slice(-1)得到的是数组[3]
console.log(last([1,2,3])); // 3
复制代码
获取数组的第 N 个元素

使用 Array.slice() 得到一个包含第一个元素的数组。 如果索引超出范围,则返回 []。(译者注:超过索引返回 undefind) 省略第二个参数 n 来获取数组的第一个元素。

const nth = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
// nth(['a','b','c'],1) -> 'b'
// nth(['a','b','b']-2) -> 'a'
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[3\]的描述,题目要求判断一个二维数组是否含有某个整数。根据题目描述,这个二维数组是按照从左到右递增和从上到下递增的顺序排序的。为了判断是否含有某个整数,可以从二维数组的右上角开始比较。 具体的解题思路如下: 1. 初始化指针p指向二维数组的右上角元素。 2. 如果p指向的元素等于目标整数,则返回true。 3. 如果p指向的元素大于目标整数,则p向左移动一列。 4. 如果p指向的元素小于目标整数,则p向下移动一行。 5. 重复步骤2-4,直到找到目标整数或者p移动到了二维数组的左下角,此时返回false。 这个解题思路可以保证在每一次比较,都能排除掉一行或一列的元素,从而提高查找效率。 所以,前端判断一个二维数组是否有某个整数的解题思路是按照上述步骤进行比较。 #### 引用[.reference_title] - *1* *2* [查找一个数是否在二维数组](https://blog.csdn.net/wangxujin666/article/details/103157374)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [二维数组的查找—在一个递增的二维数组判断给定数是否在数组](https://blog.csdn.net/ly52014/article/details/89422336)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值