Skip to content

JavaScript 编程题目

1.二维数组取值排列组合成新二维数组

题目

有一个数组:

javascript
const arr = [[1,2],3,[4,5,6]];

定义一个函数,传入arr后,返回值为一个二维数组:

javascript
[[1,3,4],[2,3,4],[1,3,5],[2,3,5],[1,3,6],[2,3,6]]

解法

javascript
function f(arr) {
    // 用于存放最后结果的空数组
    var ret = []
    // 函数result
    function fi(result, i) {
        if (i === -1) {
            ret.push(result)
        } else {
            let items = arr[i]
            if (!Array.isArray(items)) {
                items = [items]
            }
            items.forEach(item => {
                fi([item,...result], i - 1)
            });
        }
    }
    fi([], arr.length - 1)
    return ret
}
const arr = [[1,2],3,[4,5,6]];
console.log(f(arr))

补充:(用babel转为ES5)

javascript
function _toConsumableArray(arr) { 
    if (Array.isArray(arr)) { 
        for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { 
            arr2[i] = arr[i]; 
        } 
        return arr2; 
    } else { 
        return Array.from(arr); 
    } 
}

function f(arr) {
    var ret = [];
    function fi(result, i) {
        if (i === -1) {
            ret.push(result);
        } else {
            var items = arr[i];
            if (!Array.isArray(items)) {
                items = [items];
            }
            items.forEach(function (item) {
                fi([item].concat(_toConsumableArray(result)), i - 1);
            });
        }
    }
    fi([], arr.length - 1);
    return ret;
}
var arr = [[1, 2], 3, [4, 5, 6]];
console.log(f(arr));

2.数组中添加新字段组成新数组

题目

如何提取数组中的字段,然后添加新的字段,获取数据如下:

javascript
var data = [
{"id":"1","name":"华为","data":"25u6s8f545d3"},
{"id":"2","name":"小米","data":"cd58de9d3c5d"},
];

想获得的数据格式如下:

javascript
var data = [
{"id":"1","name":"华为","data":"25u6s8f545d3","mac":"25:u6:s8:f5:45:d3"},
{"id":"2","name":"小米","data":"cd58de9d3c5d","mac":"cd:58:de:9d:3c:5d"},
];

解法

javascript
var data = [
  { "id": "1", "name": "华为", "data": "25u6s8f545d3" },
  { "id": "2", "name": "小米", "data": "cd58de9d3c5d" },
];
data.forEach(item => {
  item.mac = item.data.replace(/\w{2}\B/g, '$&:')
})
console.log(data)

3.实现类似数字的倒金字塔式打印

题目

打印类似效果:

javascript
4444
333
22
1
22
333
4444

解法

javascript
function f(n) {
    for (let i = -n; i <= n; i++) {
        if (i === 0 || i === 1) {
            continue
        }
        let k = Math.abs(i)
        console.log(k.toString().repeat(k))
    }
}
f(4);

4.实现让字符串换行,每7个字符换行一次

题目

让字符串"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 每7个字符换行一次

javascript
aaaaaaa
aaaaaaa
aaaaaaa
aaaaaaa
aa

解法

javascript
var str='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
var result = str.replace(/(.{7})/g, '$1\n')
console.log(result);

5.自定义类似数组的数组类

题目

请写一段js程序,定义一个列表类List,该类包括两个成员:属性length(表示列表中的元素个数)和方法add(向列表添加元素),其中要求构造函数和add方法的参数为动态参数。

解法

javascript
class List{
    constructor(...items){
        this.items = items
        this.length = items.length
    }
    add(...items) {
        this.items.push(...items)
        this.length = this.items.length
    }
}

6.JavaScript遍历Json对象里的数组

题目

比如有这样一个对象数组:

javascript
let data = [
    {
        title: '标题一',
        tagName: 'h1'
    },
    {
        title: '标题二',
        tagName: 'h1'
    },
    {
        title: '标题三',
        tagName: 'h2'
    },
    {
        title: '标题四',
        tagName: 'h3'
    },
    {
        title: '标题五',
        tagName: 'h2'
    },
    {
        title: '标题六',
        tagName: 'h1'
    },
    {
        title: '标题七',
        tagName: 'h1'
    },
    {
        title: '标题八',
        tagName: 'h2'
    },
    {
        title: '标题九',
        tagName: 'h3'
    },
    {
        title: '标题十',
        tagName: 'h3'
    }
]

要求根据tagName的优先级,从h1开始排,一直到h6,每个h1后面直到下个h1之前的都是它的children节点,依此类推,比如上面的数据这样处理后就会像下面的格式:

javascript
let data = [
    {
      title: '标题一',
      tagName: 'h1'
    },
    {
      title: '标题二',
      tagName: 'h1',
      children: [
        {
          title: '标题三',
          tagName: 'h2'
          children: [
             {
                 title: '标题四',
                 tagName: 'h3'
             }
          ]
        },
        {
          title: '标题五',
          tagName: 'h2'
        }
      ]
    },
    {
      title: '标题六',
      tagName: 'h1'
    },
    {
      title: '标题七',
      tagName: 'h1',
      children: [
        {
          title: '标题八',
          tagName: 'h2',
          children: [
            {
              title: '标题九',
              tagName: 'h3'
            },
            {
              title: '标题十',
              tagName: 'h3'
            }
          ]
        }
      ]
    }
]

解法

javascript
function collect(arr, i, parent) {
    if (i >= arr.length) {
        return i
    }
    let current = arr[i]
    if (current.tagName > parent.tagName) {
        parent.children.push(current)
    } else {
        return i
    }
    i++
    let next = arr[i]
    if (!next) {
        return i
    }
    if (next.tagName > current.tagName) {
        current.children = []
        i = collect(arr, i, current)
    }
    return collect(arr, i, parent)
}

var ret = {
    tagName: 'h0',
    children: []
}
collect(data, 0, ret)

console.log(ret.children)

7.红包的随机分配

题目

使用random函数每次随机分配。每次得出的红包值大于 [0.01],小于 [剩余金额-剩余人数*0.01],最后一个人获得剩余全部。

解法

javascript
function rp(total, n) {
  var remain = total
  var ret = []
  for (let i = 0; i < n - 1;i++) {
    let m = Math.ceil(Math.random() * 100 * (remain - (n - (i + 1)) * 0.01)) / 100
    ret.push(m)
    remain -= m
  }
  ret.push(Number(remain.toFixed(2)))
  return ret
}

8.简化函数

题目

简化下面的函数:

javascript
function mergeJsonObject(jsonObj1, jsonObj2, jsonObj3, jsonObj4, jsonObj5) {
    let resultJsonObject = {};
    function jsonObj(jsonObj) {
        for (let attr in jsonObj) {
                resultJsonObject[attr] = jsonObj[attr];
            }
        }
        jsonObj(jsonObj1);
        jsonObj(jsonObj2);
        jsonObj(jsonObj3);
        jsonObj(jsonObj4);
        jsonObj(jsonObj5);
        return resultJsonObject;
    }

解法

javascript
function mergeJsonObject(...args) {
    let resultJsonObject = {};
    function jsonObj(jsonObj) {
        for (let attr in jsonObj) {
            resultJsonObject[attr] = jsonObj[attr];
        }
    }
    args.forEach(jsonObj)
    return resultJsonObject;
}

9.JS中将特定格式的字符串转化为json格式的问题

题目

一段字符串如下:

javascript
表名1@字段1~表名1@字段2~表名2@字段1~表名2@字段2

如何将其合理地处理为json格式,如:

javascript
{
    表名1:[字段1,字段2],
    表名2:[字段1, 字段2]
}

解法

javascript
var str = '表名1@字段1~表名1@字段2~表名2@字段1~表名2@字段2'

var obj = str.split('~').reduce((state, item) => {
  var [tname, fname] = item.split('@')
  if (state[tname]) {
    state[tname].push(fname)
  } else {
    state[tname] = [fname]
  }
  return state
}, {})

10.根据对象的属性合并对象

题目

某个对象:

javascript
var prd = {
    "id": 1,
    "department_id": 42,
    "products": [{
            "id": 12,
            "name": "49da",
            "grouped_addons": [{
                "addons": [{
                        "id": "0_0_40",
                        "name": "rice",
                        "qty": 0,
                        "unit_price": "5.00"
                    },
                    {
                        "id": "0_0_41",
                        "name": "what",
                        "qty": 1,
                        "unit_price": "15.00"
                    }
                ]
            }]
        },
        {
            "id": 12,
            "name": "49da",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_40",
                    "name": "rice",
                    "qty": 0,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_41",
                    "name": "what",
                    "qty": 1,
                    "unit_price": "15.00"
                }]
            }]
        },
        {
            "id": 42,
            "name": "345dd",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_42",
                    "name": "rice",
                    "qty": 0,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_43",
                    "name": "what",
                    "qty": 1,
                    "unit_price": "15.00"
                }]
            }]
        },
        {
            "id": 48,
            "name": "33ffg",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_44",
                    "name": "rice",
                    "qty": 0,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_45",
                    "name": "what",
                    "qty": 1,
                    "unit_price": "15.00"
                }]
            }]
        },
        {
            "id": 48,
            "name": "33ffg",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_44",
                    "name": "rice",
                    "qty": 1,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_45",
                    "name": "what",
                    "qty": 3,
                    "unit_price": "15.00"
                }]
            }]
        }
    ]
}

想要将prd中的products中id相同的对象中的grouped_addons内id相同的qty相加合并,最终的结果想要如下:

javascript
var prd = {
    "id": 1,
    "department_id": 42,
    "products": [{
            "id": 12,
            "name": "49da",
            "grouped_addons": [{
                "addons": [{
                        "id": "0_0_40",
                        "name": "rice",
                        "qty": 0,
                        "unit_price": "5.00"
                    },
                    {
                        "id": "0_0_41",
                        "name": "what",
                        "qty": 2,
                        "unit_price": "15.00"
                    }
                ]
            }]
        },
        {
            "id": 42,
            "name": "345dd",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_42",
                    "name": "rice",
                    "qty": 0,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_43",
                    "name": "what",
                    "qty": 1,
                    "unit_price": "15.00"
                }]
            }]
        },
        {
            "id": 48,
            "name": "33ffg",
            "grouped_addons": [{
                "addons": [{
                    "id": "0_0_44",
                    "name": "rice",
                    "qty": 1,
                    "unit_price": "5.00"
                }, {
                    "id": "0_0_45",
                    "name": "what",
                    "qty": 4,
                    "unit_price": "15.00"
                }]
            }]
        }
    ]
}

解法

javascript
var mp = prd.products.reduce((obj, item) => {
    if (!obj[item.id]) {
        obj[item.id] = [item]
    } else {
        obj[item.id].push(item)
    }
    return obj
}, {})
prd.products = Object.keys(mp).map(id => {
    return mp[id].reduce((state, item) => {
        item.grouped_addons[0].addons.forEach(addon => {
            var item = state.grouped_addons[0].addons.find(a => a.id === addon.id)
            item.qty += addon.qty
        })
        return state
    })
})
console.log(prd)

11.字符串重复打印

题目

写一个叫做 laugh() 的函数,它有一个参数n,表示要返回的 "ha" 的数量。

解法

javascript
// ES6
function laugh (n) {
    // ES6中`repeat`方法返回一个新字符串,表示将原字符串重复`n`次。参数如果是小数,会被取整。
    return 'ha'.repeat(n)
}

// ES5
function laugh (n) {
    var result = ''
    for (var i = 0; i < n; i++) {
        result += 'ha'
    }
    return result
}

12.按规律输出字符串

题目

从数字 1 循环访问到 20
如果数字可以被 3 整除,则输出 “Julia”
如果可以被 5 整除,则输出 “James”
如果可以同时被 3 和 5 整除,则输出 “JuliaJames”
如果不能被 3 或 5 整除,则输出该数字

解法

javascript
for (var i = 1; i < 21; i++) {
(function (n) {
    test(n);
})(i)
}
function test(num) {
  if ((num % 3 === 0) && (num % 5 === 0)) {
      console.log("JuliaJames");
  }
  if  (num % 3 === 0) {
      console.log("Julia");
  }
  if(num % 5 === 0) {
      console.log("James");
  }
  console.log(num);

13.函数参数分配

题目

假设现在有两个函数function A()和function B(),现在希望创建一个新的函数function C(),新函数的逻辑是将自己接收到的前两个参数传给函数A,剩余所有参数传给函数B,请用原生javascript实现函数C
举例:
如果调用函数C:C(a,b,c,d,e)
相当于调用函数A和函数B:A(a,b)和B(c,d,e)

解法

javascript
// ES5
function C() {
    var args = [].slice.call(arguments)
    A.apply(null, args.slice(0, 2))
    B.apply(null, args.slice(2))
}

// ES6 展开运算符
function a(v1, v2){
  console.log(v1, v2);
}

function b(...v){
  console.log(v);
}

function c(...all){
  a(all[0], all[1]);
  b(...(all.slice(2)));
}

c(1, 2, 3, 4, 5, 6, 7);

14.二次封装函数

题目

已知函数 fn 执行需要 3 个参数。请实现函数 partial,调用之后满足如下条件:
1、返回一个函数 result,该函数接受一个参数
2、执行 result(str3) ,返回的结果与 fn(str1, str2, str3) 一致

解法

javascript
function partial(fn,str1,str2) {
    var result = function(str3) {
        return fn.call(null,str1,str2,str3);
    }
    return result;
}

15.单词模式

题目

给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式。
这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应模式。

示例1:

输入: pattern = "abba", str = "dog cat cat dog"
输出: true

示例2:

输入:pattern = "abba", str = "dog cat cat fish"
输出: false
说明:
你可以假设 pattern 只包含小写字母, str 包含了由单个空格分隔的小写字母。

解法

思路:

用JS ES6的Map结构,将pattern和str作为键值对传入数组,如果Map中存在pattern中的键,则比较Str中值;如果不存在键,则看Str中的值在Map中是否存在。如果键和值都在Map中,则将键值对加入Map中
javascript
var wordPattern = function(pattern, str) {
    let map = new Map();
    //将str转为数组
    words = str.split(" ");
    //遵循指完全匹配,长度不等,直接返回
    if(pattern.length !== words.length) return false;
    for (let i = 0; i < words.length; i++){
        //判断map中是否存在该键,如果存在且值不等,则返回false
        if (map.has(pattern[i])){
            if (map.get(pattern[i]) !== words[i]) {
                    return false;
                }
        } else{
            //如果不存在键,但值存在,也返回false
            //由于map没有查看值的方法,只能去所有的值然后遍历,不知道这里有没有简便的处理方式
            let hasValue = [...map.values()].some(value => value === words[i]);
            if (hasValue) {
                return false;
            }
            //键值都不存在,则添加键值对至map中
            map.set(pattern[i], words[i]);
        }
    }
    return true;    
};

16.有效的字母异位词

题目

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例1:

输入: s = "anagram", t = "nagaram"
输出: true

示例2:

输入: s = "rat", t = "car"
输出: false

解法

javascript
var isAnagram = function(s, t) {
    if(s.length != t.length){
        return false;
    }
    let arrs = s.split("").sort();
    let arrt = t.split("").sort();
    for(let i = 0 ; i < arrs.length; i++){
        if(arrs[i] != arrt[i]){
            return false;
        }
    }
    return true;
};

17.数组去重

题目

对数组进行去重操作,只考虑数组中元素为数字或字符串,返回一个去重后的数组。

解法

对数组进行去重操作,只考虑数组中元素为数字或字符串,返回一个去重后的数组。

javascript
// ES3
function unique(arr) {
    var newArr = [];
    for (var i = 0; i < arr.length; i++) {
        var currElem = arr[i];

        if (newArr.indexOf(currElem) < 0) {
            newArr.push(currElem);
        }
    }

    return newArr;
}   
console.log(unique([1, 2, 1, 3]));

// ES5
function unique(arr) {
    return arr.filter(function (elem, index) {
        return arr.indexOf(elem) === index
    });
}
console.log(unique([1, 2, 1, 3]));

// ES6
var arr = [1, 2, 1, 3];
console.log(Array.from(new Set(arr)));

// ES7
var arr = [1, 2, 1, 3];
console.log([...new Set(arr)]);

18. 数组找单

题目

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

解法

需要维护一个对象来记录每一个元素出现的次数,使用元素的值作为key,元素出现的次数作为value。之后再遍历这个对象,找到value为1的key。对应的key就是那个元素。

javascript
function singleNumber(nums) {
  const obj = {};
  for (let i = 0; i < nums.length; i++) {
    obj[nums[i]] = obj[nums[i]] ? obj[nums[i]] + 1 : 1;
  }
  for (let key in obj) {
    if (obj[key] === 1) {
      return Number(key); // 由于 key 是 string ,因此我们这里需要转化下
    }
  }
}

console.log(singleNumber([2, 2, 1, 4, 4, 5, 5, 1, 8])); // 8

上面那种解法,创建了一个新的对象来储存结果,如果想不使用额外空间,明显是不行的。那么有没有办法可以只使用原来的数组来实现这个功能呢? 解决方案:异或操作

1.异或运算满足交换律、结合律。
1^2^...^n^...^n^...^1000,无论这两个n出现在什么位置,都可以转换成为1^2^...^1000^(n^n)的形式。

2.其次,对于任何数x,都有x^x=0,x^0=x。
所以1^2^...^n^...^n^...^1000 = 1^2^...^1000^(n^n)= 1^2^...^1000^0 = 1^2^...^1000(即序列中除了n的所有数的异或)。
异或运算是对于二进制数字而言的,比如说一个有两个二进制a、b,如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
而javascript的按位异或(即^操作)操作,则会对两个数字相应的每一对比特位执行异或操作。
比如说 1 ^ 2,本质上其实是1和2的每一对比特位执行异或操作,等价于下面
  00000000000000000000000000000001 // 数字1对应的二进制
^ 00000000000000000000000000000010 // 数字2对应的二进制
= 00000000000000000000000000000011 // 数字3对应的二进制
复制代码因此1^2的结果就为3啦。
那么如果两个相同的数字进行异或操作,结果就可想而知,答案为0啦。
如果是0和任何一个数字异或呢?结果是数字本身。

我们只需要遍历数组,将所有的值取异或,最终剩下的值,就是那个只出现一次的数字。 假设我们有一个数组,里面元素为[a, a, c, c, b, b, d]。那么我们对数组里的所有元素进行按位异或操作,即a ^ a ^ c ^ c ^ b ^ b ^ d,是不是就等价于0 ^ 0 ^ 0 ^ d = d。而d就是数组里只出现一次的元素。 那么我们可以扩展一下,对于任意满足某个元素只出现一次以外,其余每个元素均出现两次的数组,是不是可以通过这种方式来得到那个只出现一次的元素。

我们知道,两个相同的数字进行按位异或操作,得到的结果为0。并且任何数字与0进行按位异或,得到的结果是数字本身。那么假设我们有数组[a, b, b, a, c],将数组所有元素进行按位异或操作,即a ^ b ^ b ^ a ^ c,结果是不是等价于0 ^ c = c。同理可得,我们一个数组里只有某个元素只出现一次,其他都出现两次,那么将数组的所有元素都进行按位异或操作,那么结果是不是就等于那个只出现一次的元素。

javascript
/**
 * 只存在一次的数字
 * https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/1/array/25/
 * @ param {number[]} nums
 * @ return {number}
 */
function singleNumber(nums) {
  for (let i = 1; i < nums.length; i++) {
    nums[0] ^= nums[i];
  }
  return nums[0];
};

console.log(singleNumber([2, 2, 1, 4, 4, 5, 5, 1, 8]));

19.数组扁平化处理

题目

javascript
// 实现一个flatten方法,使得输入一个数组,该数组里面的元素也可以是数组,该方法会输出一个扁平化的数组。
// Example
let givenArr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
let outputArr = [1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10]

// 实现flatten方法使得
flatten(givenArr)——>outputArr

解法

javascript
function flatten(arr){
    var res = [];
    for(var i=0;i<arr.length;i++){
        if(Array.isArray(arr[i])){
            // concat() 方法用于连接两个或多个数组。返回一个新数组。
            res = res.concat(flatten(arr[i]));
        }else{
            res.push(arr[i]);
        }
    }
    return res;
}

进阶解法1(迭代器)

javascript
function flatten(arr){
    // prev 上一次调用回调时返回的累积值。如果没有提供初始值,则将使用数组中的第一个元素。item 数组中正在处理的元素。
    // array.reduce(function(accumulator, currentValue, currentIndex, arr), initialValue)
    // accumulator 和currentValue的取值有两种情况:
    // 如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;
    // 如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。
    return arr.reduce(function(prev,item){
        return prev.concat(Array.isArray(item) ? flatten(item) : item);
    },[]);
}

进阶解法2(ES6拓展运算符)

javascript
function flatten(arr){
    while(arr.some(item => Array.isArray(item))){
        arr = [].concat(...arr);
    }
    return arr;
}