资讯专栏INFORMATION COLUMN

一道简单的多维数组取值问题

tracymac7 / 3341人阅读

摘要:问题简述给予一个多维数组和一个描述取值路径的一维数组通过调用函数返回取值路径描述的值,如原问题传送门之所以想记录一下是因为之前有在刷题的习惯,后来工作忙就怠慢了,今天闲来无事就准备刷几道玩玩,然后就挑了一个比较简单的中的难度评级的题。

问题简述

给予一个多维数组和一个描述取值路径的一维数组, 通过调用函数f返回取值路径描述的值,如
f([[1, 2], [3, 4], [5, 6]], [0, 0]) -> 1

原问题传送门

之所以想记录一下是因为之前有在codewars刷题的习惯,后来工作忙就怠慢了,今天闲来无事就准备刷几道玩玩,然后就挑了一个比较简单的7kyucodewars中的难度评级)的题。

因为这题比较简单,我也没多想,上来就干,仔细想了下,很容易嘛,不就是递归吗?按大学老师教的来一套:

先找递归退出的条件,当路径取到最后或者目标数组已经取尽(这里似乎题目没有说清楚,暂定不对取值路径做限定吧)

再找递归的模式, 如果不满足递归退出的条件,则将目标数组缩小一维,传递新的取值路径并递归

然后就有了第一版代码

function getElement(array, indexes) {
  const idx = indexes.shift()
  
  if(indexes.length === 0 || array[idx].constructor !== Array ) return array[idx]
  else return getElement(array[idx], indexes)
}

然后跑了跑作者提供的简单测试用例,all passed,我就说嘛,这么简单的题目不一把过岂不是有点丢脸,然后就直接点了提交,然后就蹦了一大片的failed测试用例出来,仔细看了看失败的测试用例,并没有看懂,因为都是很多莫名奇妙的数据,并且每次返回的结果都不一致(后来才知道是随机的用例)。

之后一直以为是自己有一些边界情况没有考虑到,就前前后后又看了几次自己的答案,并没有发现什么大的问题,但是无论怎么提交都是失败。之后前前后后大概看了15分钟左右,突然就觉得是我自己把问题想简单了。

因为最近一直在看函数式的东西,突然就联想到,自己写的这个函数,并不。关于纯函数是函数式编程中最基本的概念之一,所谓纯既是要求函数没有副作用,我这里的getElement使用了Array.shift方法,会对原数组进行修改,从而产生副作用。这么一想一下就和之前每次跑用例总是产生意想不到的结果的情况联系上了,随机用例的失败原因一定是因为测试路径会有很多个,但是测试目标数组只有一个,因此有副作用的话,只有第一次测试的结果是正确的,后面都会因副作用产生不同的结果。

既然是因为数组是引用类型而产生的问题,那么直接来一个深拷贝就可以了。因为这里只是答题,所以使用一个最简单粗暴的深拷贝大法x => JSON.parse(JSON.stringify(x)),然后代码就有了第二版代码

function getElement(array, indexes) {
  array = JSON.parse(JSON.stringify(array))
  indexes = JSON.parse(JSON.stringify(indexes))
  
  const idx = indexes.shift()
  
  if(indexes.length === 0 || array[idx].constructor !== Array ) return array[idx]
  else return getElement(array[idx], indexes)
}

之后提交,所有的用例都通过了。但是还没有结束,因为自己的代码在实现上还是挺啰嗦的,同时还使用了深拷贝大法,有没有更简单的方法呢?

有的。如果仔细思考一下,这里的解题的思路其实和Array.reduce的模式很像

对一个数组进行遍历(对路径数组进行遍历)

每次遍历返回一个值,并作为参数传入下一次遍历(对目标函数的降维)

在遍历完成后,返回一个结果(取值路径对应的值)

因此利用Array.reduce,这个问题一行代码就可以解决,如下

function getElement(array, indexes) {
  return indexes.reduce((a, i) => a[i], array);
}

同样多考虑一下,它是纯函数吗?是的,它是纯的。因为这里只做了取值的操作(a[i]),并不涉及任何的修改原数组的操作。这个答案也是在我提交后,所有答案中实现方案最好的一个。

当然还有其他的暴力破解法,我觉的想法也不错,比如

function getElement(array, indexes) {
  return eval(`array[${indexes.join("][")}]`);
}

还有利用spread运算符的方法,如

const getElement = (array,[index,...moreIndices]) => moreIndices.length ? getElement( array[index], moreIndices ) : array[index]

所以说工作累了,或者闲来无事,刷刷题还是挺有意思的,可以看见一些自己平时很熟悉但是在需要用时又难以想起的知识。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92220.html

相关文章

  • 一道面试题引起思考

    摘要:这个时候查了下正则表达式的文档文档点击这里,发现有一个方法,可以返回匹配成功的结果。那么我来总结下文章想表达的内容对于具有固定格式的字符串,可以考虑使用正则表达式来识别和匹配。 今天在认真干(划)活(水)的时候,看到群里有人发了一道头条的面试题,就顺便看了一下,发现挺有意思的,就决定分享给大家,并且给出我的解决方案和思考过程。 题目如下: 实现一个get函数,使得下面的调用可以输出正确...

    xiaoqibTn 评论0 收藏0
  • 一道面试题引起思考

    摘要:这个时候查了下正则表达式的文档文档点击这里,发现有一个方法,可以返回匹配成功的结果。那么我来总结下文章想表达的内容对于具有固定格式的字符串,可以考虑使用正则表达式来识别和匹配。 今天在认真干(划)活(水)的时候,看到群里有人发了一道头条的面试题,就顺便看了一下,发现挺有意思的,就决定分享给大家,并且给出我的解决方案和思考过程。 题目如下: 实现一个get函数,使得下面的调用可以输出正确...

    snowLu 评论0 收藏0
  • 一道面试题引起思考

    摘要:这个时候查了下正则表达式的文档文档点击这里,发现有一个方法,可以返回匹配成功的结果。那么我来总结下文章想表达的内容对于具有固定格式的字符串,可以考虑使用正则表达式来识别和匹配。 今天在认真干(划)活(水)的时候,看到群里有人发了一道头条的面试题,就顺便看了一下,发现挺有意思的,就决定分享给大家,并且给出我的解决方案和思考过程。 题目如下: 实现一个get函数,使得下面的调用可以输出正确...

    hlcc 评论0 收藏0
  • 一道有意思编程思考题:【妖怪和和尚过河问题

    摘要:不断地穷举下一步的可能性,直到最终达成目标。表示船在左边表示船在右边打印答案妖怪过河数僧人过河数船上是否安全左岸是否安全右岸是否安全过河后的数据过河后的数据简单地看下深度优先搜索的函数,每次根据船所在的位置,枚举下个状态值。 无意中看到这么一道题,觉得很有意思,题目如下: 有三个和尚和三个妖怪要利用唯一的一条小船过河,这条小船一次只能载两个人,同时,无论是在河的两岸还是在船上,只要妖怪...

    asce1885 评论0 收藏0

发表评论

0条评论

tracymac7

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<