数组升维"/>
携程春招题目字符串截取和数组升维
编程风格
简单陈述一下文中代码使用的编程风格:
使用
ES5
,以避免有些在线编程平台不支持ES6
的状况(所以在这里没有用new Set()
)Airbnb 代码规范,不使用单
var
模式变量定义(
var
),函数体(body
),return
值三者用空行隔开,逻辑鲜明有意义的变量命名
适当的函数抽取,一个函数只做一件事情
另外还有 根据不同场合使用合适的类型判断方式:
Array.isArray
判断数组,Object.prototype.toString.call
来判断纯对象typeof
判断基本类型和function
instanceof
来判断自定义的对象
1. 字符串截取
题目
描述
给定一个长度小于 50 且包含字母和数字的任意字符串,要求按顺序取出当中的数字和英文字母,数字需要去重,重新排列后的字符串数字在前,字母在后。
输入
需要截取的字符串(包含数字和字母)
输出
按照要求重新排列的字符串
样例输入
'携程C2t0r1i8p2020校招'
样例输出:
'2018Ctrip'
解答
肯定有同学表示第一题不值得分析。但我还是想抛砖引玉一下,思路如下:
字符串转数组:
str.split('')
(进而使用数组的各种操作方法,如arr.forEach
)判断字符串值是否为数字:
/\d/.test(element)
或者Number.isNaN(Number(element)
判断字符串值是否为字母:
/[a-zA-Z]/.test(element)
数字字符串去重(利用数组去重)
输出数字+字母
由此有了这一版代码:
条件 1~3
function handleStr(str) {var arr = str.split('');var nums = '';var words = '';arr.forEach(function (element) {if (/\d/.test(element))) {nums += element;} else if (/[a-zA-Z]/.test(element) ) {words += element;}});return uniqueStr(nums) + words;
}
去重
作为前端开发超高频面试题,相信大家早已对数组去重熟捻于心:
基本类型去重:
function unique(arr) {return arr.filter(function (element, index) {return arr.indexOf(element) === index;});
}
基本+复杂类型去重:
function unique(arr) {var hash = {};return arr.filter(function (element) {if (hash.hasOwnProperty(element)) {return false;}hash[element] = true;return true;});
}
由于数字去重(str
,基本类型)基于数组去重,我们要对原来的数组去重做一点修改:
function uniqueStr(str) {var arr = str.split('');return arr.filter(function (element, index) {return arr.indexOf(element) === index;}).join('');
}
string.split()
和 array.join()
帮助我们自由的游走在字符串和数组间。
最终解答
function handleStr(str) {var arr = str.split('');var nums = '';var words = '';arr.forEach(function (element) {if (/\d/.test(element)) {nums += element;} else if (/[a-zA-Z]/.test(element) ) {words += element;}});return uniqueStr(nums) + words;
}function uniqueStr(str) {var arr = str.split('');return arr.filter(function (element, index) {return arr.indexOf(element) === index;}).join('');
}// 测试
console.log(handleStr('携程C2t0r1i8p2020校招'));
// 2018Ctrip
2. 数组升维
题目
描述
对一维数组,根据 type
类型分组成二维数组
输入
输入的参数可能是空数组
[]
,空对象null
,undefined
,数字,字符串等异常值;也可能是结构为
[{ type, content}]
的有效值;甚至是
[null, null, (type, content)]
等有效和非法值混合的数据。
输出
当输入数据不合法时,输出空数组
[]
当输入数据有效时(请先过滤数组里的异常元素),然后将相同
type
值的元素合并,形成新元素{"type": "A", "contents": [content1, content2]}
,其中,contents
为一个数组,元素为所有 type 值相同的content
值。注意,输出的是一个标准
JSON
格式
样例输入
var input = [null, 2, "test", undefined, {"type": "product","content": "product1"
}, {"type": "product","content": "product2"
}, {"type": "tag","content": "tag1"
}, {"type": "product","content": "product3"
}, {"type": "tag","content": "tag2"
}];
样例输出
[{"type":"product","contents":["product1","product2","product3"]},{"type":"tag","contents":["tag1","tag2"]}]
解答
乍一看要求颇多,我们一点点来拆解:
条件 1
当输入数据不合法时,输出空数组
[]
什么数据不合法?输入值不为 JSON
格式(即 array
类型);
还有呢?输入值为 JSON
格式(即 array
类型),但长度为 0
;
由此写下第一句:
function groupList(list) {if (!Array.isArray(list) || list.length === 0) { return []; }
}
条件 2
当输入数据有效时(请先过滤数组里的异常元素)
过滤掉[]
,空对象 null
,undefined
,数字,字符串等异常元素:
function groupList(list) {if (!Array.isArray(list) || list.length === 0) { return []; }var validItems = getValidItems(list);
}function getValidItems(json) {return json.filter(function (element) {return isPureObject(element)});
}function isPureObject(item) {return Object.prototype.toString.call(item).slice(8, -1) === 'Object' && item !== null ? true : false;
}
条件 3(隐藏条件)
等等,结构不为 { "type": "xx", "content": "yy" }
的值,是不是也为异常元素呢?为此在 getValidItems
里加上一句:
function getValidItems(json) {return json.filter(function (element) {return isPureObject(element) && element.type && element.content;});
}
条件 4
过滤完成后,将相同
type
值的元素合并,形成新元素
function groupList(list) {if (!Array.isArray(list) || list.length === 0) { return []; }var validItems = getValidItems(list);var result = {};validItems.forEach(function (item) {if (result.hasOwnProperty(item.type)) {result[item.type].push(item.content);} else {result[item.type] = [];result[item.type].push(item.content);}});return ...;
}
条件 5
貌似我们已经完成了将相同 type
值合并这一步骤,但是
注意,输出的是一个标准
JSON
格式
而且当前的结构是 {type1: contentsArr1, type2: contentsArr2}
的结构,与题目要求的:[ {type1: contentsArr1}, {type1: contentsArr2}]
不相同。
不难,再加一步便是:
function jsonResultGenerator(obj) {var result = [];Object.keys(obj).forEach(function (key) {result.push({ type: key, contents: obj[key] });});return result;
}
最终解答
完整的代码:
function groupList(list) {if (!Array.isArray(list) || list.length === 0) { return []; }var validItems = getValidItems(list);var result = {};validItems.forEach(function (item) {if (result.hasOwnProperty(item.type)) {result[item.type].push(item.content);} else {result[item.type] = [];result[item.type].push(item.content);}});return jsonResultGenerator(result);
}function getValidItems(json) {return json.filter(function (element) {return isPureObject(element) && element.type && element.content;});
}function isPureObject(item) {return Object.prototype.toString.call(item).slice(8, -1) === 'Object' && item !== null ? true : false;
}function jsonResultGenerator(obj) {var result = [];Object.keys(obj).forEach(function (key) {result.push({ type: key, contents: obj[key] });});return result;
}// test
var input = [null, 2, "test", undefined, {"type": "product","content": "product1"
}, {"type": "product","content": "product2"
}, {"type": "tag","content": "tag1"
}, {"type": "product","content": "product3"
}, {"type": "tag","content": "tag2"
}];console.log(JSON.stringify(groupList(input)));
// [{"type":"product","contents":["product1","product2","product3"]},{"type":"tag","contents":["tag1","tag2"]}]
总结
回到文章题目本身上来,什么算是有趣的前端笔试题?
不是固定套路的,不考“背诵能力”的
能体现 JS 能力的,考察点广泛全面的
和前端密切相关的,和实际开发有联系的
注重细节复杂度,而不是纯粹的“算法复杂度”(仅针对前端开发,仅为博主一家之言)
如果是现场面试手写编程题,我觉得应该再加上一条:
能体现编程素养的,注重纵向拓展的
更多推荐
携程春招题目字符串截取和数组升维
发布评论