124:DNA Pairing
几点收获:如何构造元素为数组的数组[[],[],[]],当用arr.push(str[i])时,arr里的数组项都是字符串,而不会是数组,我甚至构造了一个for循环来构造这样一个函数,
var arr=[],brr=[]; for(var i =0;i<str.length;i++){ brr.push(arr); }
简直神经病,我直接arr.push([str[i]])不就好了;
我还一度尝试用双重循环,再在内循环时给arr[i][j]赋值的方式试图构造上述数组,结果一直报错cannot set property 0 of undefined,百度居然还搜是不是循环条件超出,真是愚笨得可以,明明就是你只定义了一个空数组,你都没法访问到arr[i][j],怎么给它赋值,所以你改循环条件肯定没用,只要有arr[i][j]就会一直报错,那个报错的意思就是不能给第0项值为undefined的元素赋值,你把j改成从1开始循环,就变成了cannot set property 1 of undefined,是一样的道理。
另外,寻找配对元素这个方法倒不是难点,我也想到了switch语句,也想到了之前罗马数字和阿拉伯数字互转的算法题,里面用到了查找替换的思路,定义了一个对象或数组,把结果都穷举出来,然后通过数组或对象去访问里面的结果,就变得非常简单了。
126:如何判断一个值是不是布尔值。用typeof操作符是最快捷的,将typeof操作符得到的值与boolean比较是不是全等即可。记住typeof是操作符,不是函数,跟var一样,所以后面不用加括号。
127:sorted union.
收获1:arguments是一个对象而非一个数组,虽然可以用arguments[i]来访问,但它仍然是一个对象,只不过里面的属性名是"0"、"1"、"2",所以可以用arguments[i]访问。可以用for循环加arr.push()将其转化成一个数组。
收获2:数组的splice()方法,非常强大的一个方法,可以实现数组元素的增删改,有3个参数,分别是定位,要删除的元素个数,要替换的内容。如果第3个参数为空,就实现了删除,如果第2个参数为0,就实现了添加,如果3个参数都有值且非0,就实现了修改。
收获3:数组的reduce()方法,可以对数组的每一项元素从左至右应用一个函数,这个函数里你想做什么就做什么。有两个典型的应用,数组元素的累加和数组的扁平化,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce。在这个算法题中,我先用一个双重循环去掉了两项元素之间的重复元素splice,然后再把这两个元素用concat()方法合并,这样从左至右逐项的去重合并,就像贪吃蛇一样慢慢地就达到了想要的目的。
128:convert HTML Entities.
收获1:正则表达式https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp。/.../g,后面有g标志表示会匹配目标字符串里所有符合该模式的字符,否则就只会匹配遇到的第一个符合要求的字符。如果要查找替换某一类东西,那一定记得不要忘了g。一般情况下都要加g,想想哪怕是精确查找也只会将模式弄得复杂一点,匹配度更高,也不会用不加g的方式来匹配,只有一种情况会不用加g比较合适,那就是做判断的时候,比如只要这个字符串里有某个字符,我就做某件事,那可以不用g,节约时间和内存嘛。
收获2:从上面的链接可以了解到,正则表达式可以很清楚地分为字符类别/d/S/w...,字符集合[a-z],边界^&,分组和反向引用()\1,数量词*+?{n,m}。
收获3:查找用匹配方法,str.match(/.../g);查找替换用str.replace(/.../g,expression/function)。我用了最原始的办法穷举法,一个符号对应一个匹配模式,一个匹配模式对应一个替换语句,虽然能做到,但是明显太复杂。后来才知道可以用链式操作,一看链接里的说明发现replace方法返回的是替换后的字符串,而字符串又可以应用replace方法,那不就正好可链起来了嘛,要知道jquery的原理也是这样,在每个方法后面都返回该对象,而该对象又可以继续应用方法,这样就形成了美观简单的链式操作。
129:spinal type case
将字符串转换为 spinal case。Spinal case 是 all-lowercase-words-joined-by-dashes 这种形式的,也就是以连字符连接所有小写单词。
难点1:怎么应付"thisIsSpinalTap"这种形式的字符串,要是只查找替换空格和下划线还好,只需用/[_\s]/g来匹配就好\s是指空白符不只是空格还包括换行制表符等。观察一下其实也能知道只要查找到字符串里的大写字母然后在前面加一个空格或下划线什么的,最后统一替换不就好了?思路找对了,然后就是怎么做到添加而不是修改匹配字符呢?想到了捕获组,先把大写字母用小括号捕获了,然后替换字符用"_$1"即可。
难点2:为了误伤其他有大写字母但不需替换的同类,要先做一个判断,先做一个字符串里是否有空格的匹配判断/[_\s]/g并赋值给match,如果match为false就替换。这里可以延伸一下,如果这样呢"this IsSpinalTap"?那这里就要精确匹配下了,/[a-z][A-Z]/g。但这里如何替换[A-Z]又不影响前面的小写字母呢?简单str.replace(/([a-z])([A-Z])/g,"$1_$2"),所以,这就是第二种解法了(第一种是做match判断,把那种特殊字符串单独拎出来)。
易错点1:[]和()懂区别但还是不会用,[]是字符集,换句话讲就是一个字符的集合,匹配其中的任意一个字符就算匹配了,通常都是放字母的。而()是捕获组,这个捕获的对象是会被返回并拿来应用的,如果你需要用到它,那么一定不要忘了把它括起来。
然后发现toLowerCase()也可以链式操作,那就完美了,一条语句就解决了这个算法。
function convert(str){ return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[_\s]/g,"-").toLowerCase(); }
return str.replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[_\s]/g,"-").toLowerCase();