题目:
请在 index.html 文件中,编写 arraysSimilar 函数,实现判断传入的两个数组是否相似。具体需求:
1. 数组中的成员类型相同,顺序可以不同。例如 [1, true] 与 [false, 2] 是相似的。
2. 数组的长度一致。
3. 类型的判断范围,需要区分: String, Boolean, Number, undefined, null, 函数,日期, window.
当以上全部满足,则返回 "判定结果: 通过",否则返回 "判定结果: 不通过"。
- var result = function() {
- //以下为多组测试数据
- var cases = [{
- arr1: [1, true, null],
- arr2: [null, false, 100],
- expect: true
- },
- {
- arr1: [function() {},
- 100],
- arr2: [100, {}],
- expect: false
- },
- {
- arr1: [null, 999],
- arr2: [{},
- 444],
- expect: false
- },
- {
- arr1: [window, 1, true, new Date(), "hahaha", (function() {}), undefined],
- arr2: [undefined, (function() {}), "okokok", new Date(), false, 2, window],
- expect: true
- },
- {
- arr1: [new Date()],
- arr2: [{}],
- expect: false
- },
- {
- arr1: [window],
- arr2: [{}],
- expect: false
- },
- {
- arr1: [undefined, 1],
- arr2: [null, 2],
- expect: false
- },
- {
- arr1: [new Object, new Object, new Object],
- arr2: [{},
- {},
- null],
- expect: false
- },
- {
- arr1: null,
- arr2: null,
- expect: false
- },
- {
- arr1: [],
- arr2: undefined,
- expect: false
- },
- {
- arr1: "abc",
- arr2: "cba",
- expect: false
- }];
- //使用for循环, 通过arraysSimilar函数验证以上数据是否相似,如相似显示"通过",否则"不通过",所以大家要完成arraysSimilar函数,具体要求,详见任务要求。
- for (var i = 0; i) {
- if (arraysSimilar(cases[i].arr1, cases[i].arr2) !== cases[i].expect) {
- document.write("不通过!case" + (i + 1) + "不正确!arr1=" + JSON.stringify(cases[i].arr1) + ", arr2=" + JSON.stringify(cases[i].arr2) + " 的判断结果不是" + cases[i].expect);
- return false;
- }
- }
- return true;
- } ();
- document.write("判定结果:" + (result ? "通过": "不通过"));
这个文件为 testData.js。主要任务是完成 arraysSimilar 函数。
1、判断 2 个参数是否都是数组,不是就返回 false;
2、判断 2 个数组长度是否一致,不是直接返回 fasle;
3、新建 2 个临时数组 temp1,temp2 并初始化为 0,用来存放 arr1 和 arr2 中各种类型的个数。
var temp1 = [0, 0, 0, 0, 0, 0, 0, 0];
var temp2 = [0, 0, 0, 0, 0, 0, 0, 0];
4、遍历 2 个 arr1 和 arr2,每遍历一个元素,将对应类型加 1。
5、完成 arr1 和 arr2 的遍历后,通过 temp1.toString() 和 temp2.toString() 是否相等得出 2 个数组是否相似。
- <!DOCTYPE HTML>
- <html>
- <meta charset="utf-8">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=gb18030">
- <title>
- Untitled Document
- </title>
- </head>
- <body>
- <script type="text/javascript">
- /*
- * param1 Array
- * param2 Array
- * return true or false
- */
- function arraysSimilar(arr1, arr2) {
- console.log("arr1为" + arr1);
- console.log("arr2为" + arr2);
- if (! (arr1 instanceof Array) || !(arr2 instanceof Array)) {
- document.write(false + "<br/>");
- return false;
- } else if (arr1.length != arr2.length) {
- document.write(false + "<br/>");
- return false;
- }
- var temp1 = [0, 0, 0, 0, 0, 0, 0, 0];
- var temp2 = [0, 0, 0, 0, 0, 0, 0, 0];
- //初始化temp1
- for (i = 0; i < arr1.length; i++) {
- console.log("arr1的第" + i + "个值为" + arr1[i]);
- switch (jsType(arr1[i])) {
- case "String":
- temp1[0]++;
- break;
- case "Boolean":
- temp1[1]++;
- break;
- case "Number":
- temp1[2]++;
- break;
- case "Undefined":
- temp1[3]++;
- break;
- case "Null":
- temp1[4]++;
- break;
- case "Function":
- temp1[5]++;
- break;
- case "Date":
- temp1[6]++;
- break;
- case "Window":
- temp1[7]++;
- break;
- }
- console.log("arr2的第" + i + "个值为" + arr2[i]);
- //初始化temp2
- switch (jsType(arr2[i])) {
- case "String":
- temp2[0]++;
- break;
- case "Boolean":
- temp2[1]++;
- break;
- case "Number":
- temp2[2]++;
- break;
- case "Undefined":
- temp2[3]++;
- break;
- case "Null":
- temp2[4]++;
- break;
- case "Function":
- temp2[5]++;
- break;
- case "Date":
- temp2[6]++;
- break;
- case "Window":
- temp2[7]++;
- break;
- }
- }
- //判断temp1和temp2是否相等
- if (temp1.toString() === temp2.toString()) {
- document.write(true + "<br/>");
- return true;
- } else {
- document.write(false + "<br/>");
- return false;
- }
- }
- //返回参数的javascript类型
- function jsType(arg) {
- //判断字符串
- if (typeof arg == "string") {
- console.log("string");
- return "String";
- }
- //判断Boolean
- if (typeof arg == "boolean") {
- console.log("boolean");
- return "Boolean";
- }
- //判断Number
- if (typeof arg == "number") {
- console.log("Number");
- return "Number";
- }
- //判断Undefined
- if (typeof arg == "undefined") {
- console.log("Undefined");
- return "Undefined";
- }
- //判断Null(不考虑IE8以下) //看了答案发现直接=== null判断就好了
- if (Object.prototype.toString.apply(arg) == "[object Null]") {
- console.log("Null");
- return "Null";
- }
- //判断Function
- if (typeof arg == "function") {
- console.log("Function");
- return "Function";
- }
- //判断日期
- if (arg instanceof Date) {
- console.log("Date");
- return "Date";
- }
- //判断window //看了答案发现直接=== window 判断就好了
- if (arg instanceof Window) {
- console.log("window");
- return "Window";
- }
- }
- </script>
- <script src="testData.js">
- </script>
- </body>
- </html>
虽然代码略粗糙,但是功能完成了。网上看了其他人的答案确实不同的人做法不一样,有些值得借鉴的地方。
建一个类型对象数组 obj,初始化为零,arr1 遍历时每个元素对应的类型加一,arr2 遍历时每个元素对应的类型减一,最终判断 obj 里所有键的值都为 0 即相似数组。
- function check(i){
- //除了function 其他的引用类型用instanceof来判定
- if(i instanceof Date){
- return 'date';
- }
- else if(i instanceof Window){
- return 'window';
- }
- // typeof可以判断基本类型(number string boolean null(typeof 返回object) undefined )和引用类型的function类型
- if(typeof i === 'number')return 'number';
- else if(typeof i === 'string')return 'string';
- else if(typeof i === 'boolean')return 'boolean';
- else if(typeof i === 'function')return 'function';
- //typeof null 返回 object
- else if(typeof i === 'object'){
- if(i === null){
- return 'null';
- }else{
- return 'object';
- }
- }
- else if(typeof i === 'undefined'){
- return 'undefined';
- }
- }
- function arraysSimilar(arr1, arr2){
- if(!arr1||!arr2){return false;}
- if(!(arr1 instanceof Array )||!(arr2 instanceof Array))return false;
- if(arr1.length!=arr2.length)return false;
- var obj={
- 'number':0,
- 'string':0,
- 'boolean':0,
- 'undefined':0,
- 'null':0,
- 'function':0,
- 'date':0,
- 'object':0,
- 'window':0
- };
- for(var i=0;i){
- var r1=check(arr1[i]);
- var r2=check(arr2[i]);
- obj[r1]++;
- obj[r2]--;
- }
- for(var o in obj){
- if(obj[o]!=0)return false;
- }
- return true;
- }
还有一个答案,差不多算标准答案,当然这种题也没有标准答案。和上个答案的差别是,用 map(在 js 中也就是对象)存放数据类型和次数,这个 map 初始化为 {},在后面动态生成的。
- /**
- * String, Boolean, Number, undefined, null, 函数,日期, window
- */
- function arraysSimilar(arr1, arr2) {
- // 判断参数,确保arr1, arr2是数组,若不是直接返回false
- if (!(arr1 instanceof Array)
- || !(arr2 instanceof Array)) {
- return false;
- }
- // 判断长度
- if (arr1.length !== arr2.length) return false;
- var i = 0,
- n = arr1.length,
- countMap1 = {}, // 用来计算数组元素数据类型个数的map,key是TYPES中的类型字符串,value是数字表示出现次数。
- countMap2 = {},
- t1, t2,
- TYPES = ['string', 'boolean', 'number', 'undefined', 'null',
- 'function', 'date', 'window'];
- // 因为是无序的,用一个对象来存储处理过程。key为类型, value为该类型出现的次数。
- // 最后校验:若每一种数据类型出现的次数都相同(或都不存在),则证明同构。
- for (; i < n; i++) {
- t1 = typeOf(arr1[i]);
- t2 = typeOf(arr2[i]);
- if (countMap1[t1]) {
- countMap1[t1]++;
- } else {
- countMap1[t1] = 1;
- }
- if (countMap2[t2]) {
- countMap2[t2]++;
- } else {
- countMap2[t2] = 1;
- }
- }
- // 因为typeof只能判断原始类型,且无法判断null(返回"object"),所以自己写typeof方法扩展。
- function typeOf(ele) {
- var r;
- if (ele === null) r = 'null'; // 判断null
- else if (ele instanceof Array) r = 'array'; // 判断数组对象
- else if (ele === window) r = 'window'; // 判断window
- else if (ele instanceof Date) r = 'date' // 判断Date对象
- else r = typeof ele; // 其它的,使用typeof判断
- return r;
- }
- for (i = 0, n = TYPES.length; i < n; i++) {
- if (countMap1[TYPES[i]] !== countMap2[TYPES[i]]) {
- return false;
- }
- }
- return true;
- }
还有一个比较简洁也好理解的解法
- /*
- * param1 Array
- * param2 Array
- * return true or false
- */
- function type(a) {
- return a === null ? '[object Null]': Object.prototype.toString.apply(a); //hack ie678
- }
- function arraysSimilar(arr1, arr2) {
- if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length != arr2.length) {
- return false;
- }
- var arr3 = [];
- var arr4 = [];
- var x;
- for (var i in arr1) {
- arr3.push(type(arr1[i]));
- arr4.push(type(arr2[i]));
- }
- if (arr3.sort().toString() == arr4.sort().toString()) {
- return true;
- } else {
- return false;
- }
- }
还有一个精妙的解法,我对这种不感兴趣,没仔细看。
- var global = window;
- function arraysSimilar(arr1, arr2){
- return (arr1 instanceof Array && arr2 instanceof Array) && JSON.stringify(arr1.map(function(v) {
- return null === v ? "☀" : (v instanceof Date ? "❤" : (v === global ? "❀" : typeof v));
- }).sort()) === JSON.stringify(arr2.map(function(v) {
- return null === v ? "☀" : (v instanceof Date ? "❤" : (v === global ? "❀" : typeof v));
- }).sort());
- }
参考:http://www.imooc.com/qadetail/62836
来源: