业务代码问题记录

二维数组合并

输入这样一个数组

1
2
3
4
[
['A', 'B'],
['C', 'D'],
]

要求经过处理得到这样一个结果, 也就是 2x2 = 4个

1
2
3
4
5
6
[
'AC',
'AD',
'BC',
'BD',
]

或者这个数组

1
2
3
4
5
[
['A', 'B'],
['C', 'D'],
['E', 'F', 'G'],
]

要求经过处理得到这样一个结果, 也就是 2x2x3 = 12个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
'ACE',
'ACF',
'ACG',
'ADE',
'ADF',
'ADG',
'BCE',
'BCF',
'BCG',
'BDE',
'BDF',
'BDG',
]

代码也很简单,没啥难度,只是做一下记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let arr = [
['A', 'B'],
['C', 'D'],
['E', 'F', 'G'],
]

const foo = (origin, index = 1, next) => {
let result = []
if (origin.length === 1 || origin.length === 0) {
return origin[0] || []
}
if (index === 1) {
next = origin[0]
}
next.forEach(ele => {
origin[index].forEach(item => {
result.push(ele + item)
})
})
if (index === origin.length - 1) {
return result
}
return foo(origin, index + 1, result)
}
console.log('result', foo(arr))

Nest.js操控MongoDB的方法

一、安装 nestjs/mongoose 以及 mongoose 模块

Nest 操作 Mongodb 官方文档:https://docs.nestjs.com/techniques/mongodb

1
npm install --save @nestjs/mongoose mongoose

二、配置数据库连接地址

在 app.module.ts 中配置数据库连接

1
2
3
4
5
6
7
8
import { Module } from '@nestjs/common'; 
import { MongooseModule } from '@nestjs/mongoose';

@Module({
imports: [MongooseModule.forRoot('mongodb://localhost/koa',{ useNewUrlParser: true })]
})

export class ApplicationModule {}

三、配置 Schema

1
2
3
4
5
6
7
8
import * as mongoose from 'mongoose'; 

export const ArticleSchema = new mongoose.Schema({
title: String,
keywords:String,
author: Number,
status: String,
});

四、在控制器对应的 Module 中配置 Model

1
2
3
4
5
6
7
8
9
10
11
12
import { Module } from '@nestjs/common'; 
import { NewsController } from './news.controller';
import { NewsService } from './news.service';
import { ArticleSchema } from './schemas/article.schema';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
imports: [MongooseModule.forFeature([{ name: 'Article', schema: ArticleSchema,collection:"article" }])], controllers: [NewsController],
providers: [NewsService]
})

export class NewsModule {}

五、在服务里面使用 InjectModel 获取数据库 Model 实现 操作数据库

1
2
3
4
5
6
7
8
9
10
import { Injectable } from '@nestjs/common'; 
import { InjectModel } from '@nestjs/mongoose';

@Injectable()
export class NewsService {
constructor(@InjectModel('Article') private readonly articleModel) {}
async findAll() {
return await this.articleModel.find().exec();
}
}

记录一次编程问题

先说问题

有如下一个数据,但它是用数组存放的具有联级关系的数据,需要将其转化为适合UI库的数据结构树状结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const data = [
"办公设备、附件和用品>>办公用品>>书写工具>>毛笔",
"造纸原料和纸制品>>纸制品>>个人纸制品>>餐巾纸和餐巾",
"造纸原料和纸制品>>纸制品>>个人纸制品>>丝巾",
"办公设备、附件和用品>>办公用品>>测试分类>>苹果",
"其它",
"办公设备、附件和用品>>办公用品>>测试分类>>荔枝",
"办公设备、附件和用品>>家具用品>>床头用品>>枕头",
"食品、饮料和烟草>>肉和家禽产品>>加工和处理过的肉>>鲜的加工和处理过的肉",
"食品、饮料和烟草>>巧克力、糖、甜品和糖果>>糖果>>口香糖",
"食品、饮料和烟草>>饮料>>咖啡和茶>>咖啡饮料",
"食品、饮料和烟草>>饮料>>非酒精饮料>>泉水和矿泉水",
"办公设备、附件和用品>>办公用品>>书写工具>>水笔",
"造纸原料和纸制品>>纸制品>>个人纸制品>>纸巾",
"食品、饮料和烟草>>巧克力、糖、甜品和糖果>>巧克力、糖和甜品>>巧克力和巧克力代用品",
"食品、饮料和烟草>>饮料>>非酒精饮料>>水",
"食品、饮料和烟草>>乳制品和蛋>>牛奶和黄油产品>>贮藏的牛奶和黄油产品",
"食品、饮料和烟草>>预制食品和罐头>>方便什锦和用品>>方便什锦小吃",
"食品、饮料和烟草>>饮料>>咖啡和茶>>袋茶",
"食品、饮料和烟草>>面包和烘焙食品>>蛋糕、派和糕点>>新鲜蛋糕、派和糕点",
"休闲零食",
"食品、饮料和烟草>>饮料>>咖啡和茶>>非乳场生产的乳品饮料",
"服装、箱包、个人护理用品>>个人护理用品>>洗浴、身体护理品>>化妆品",
"食品、饮料和烟草>>饮料>>非酒精饮料>>软饮料",
"食品、饮料和烟草>>肉和家禽产品>>加工和处理过的肉>>贮藏加工和处理过的肉",
"食品、饮料和烟草>>谷类和豆类制品>>豆类>>豆粉",
"食品、饮料和烟草>>预制食品和罐头>>小吃>>坚果和水果干"
]

适合的结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[
{
"value": "办公设备、附件和用品",
"lable": "办公设备、附件和用品",
"children": [
{
"value": "办公用品",
"lable": "办公用品",
"children": [
{
"value": "书写工具",
"lable": "书写工具",
"children": [
{
"value": "毛笔",
"lable": "毛笔"
}
...
]
}
...
]
}
...
]
}
]

首先的思路是切分字符串

使用String.prototype.split()将字符串切分为数组,方便分级

1
2
3
4
5
6
7
8
[
[ '办公设备、附件和用品', '办公用品', '书写工具', '毛笔' ],
[ '造纸原料和纸制品', '纸制品', '个人纸制品', '餐巾纸和餐巾' ],
[ '造纸原料和纸制品', '纸制品', '个人纸制品', '丝巾' ],
[ '办公设备、附件和用品', '办公用品', '测试分类', '苹果' ],
[ '其它' ],
...
]

简单点的就是死办法,看数据貌似只有4级,所以套四重循环就可以解决

但是这样真的很蠢,很笨,一旦数据发生变化,这就白写了

按照思路来先把数组中的字符串进行切分

1
2
3
4
5
6
const treeArr = []
const analysisData = (data) => { // 这样就得到了一个切分好的数组
data.forEach((ele, index) => {
treeArr.push(ele.split('>>'))
})
}

其次是观察数据结构

观察切分好的数据结构,有的是只有一级,没有子级的,有的呢,可能有四级也可能有三级。这样就对分级存放数据结构带来了很大的困扰。

这样就需要对每一条数据进行判断,这个判断的过程就抽出来写成一个函数就行了。

1
2
3
4
5
6
7
const treeArr = []
const analysisData = (data) => {
data.forEach(ele => {
const eleArr = ele.split('>>')
judgeData(treeArr, eleArr, 0)
})
}

这个函数接收3个传参

  • treeArr 存放预期数据结构的数组
  • eleArr 每一条原始的字符串切分数组
  • step 进行到第几步了

judgeData函数负责对传进来的每一条原始的字符串切分数组,进行判断,如果符合要求就push,不符合要求就递归判断,关键是递归的思想

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const judgeData = (treeArr, eleArr, step) => {
if (!treeArr.some(item => {
if (item.value === eleArr[step]) {
return true
}
})) {
const treeSon = {
value: eleArr[step],
lable: eleArr[step]
}
treeArr.push(treeSon)
if (eleArr[step + 1] !== undefined) {
treeSon.children = []
judgeData(treeSon.children, eleArr, step + 1)
}
} else {
treeArr.forEach(ele => {
if (ele.value === eleArr[step]) {
judgeData(ele.children, eleArr, step + 1)
}
})
}
}

treeArr传入的并不是预先在最开始设置的那个treeArr,而是每次存放预期数据结构的数组,因为js的对象是引用类型的所以,从对象上拆children下来传进去,并不影响存值,而step则是为了记录分级的层级,避免不知道到哪一步了,乱分。

这里贴上完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const data = [
"办公设备、附件和用品>>办公用品>>书写工具>>毛笔",
"造纸原料和纸制品>>纸制品>>个人纸制品>>餐巾纸和餐巾",
"造纸原料和纸制品>>纸制品>>个人纸制品>>丝巾",
"办公设备、附件和用品>>办公用品>>测试分类>>苹果",
"其它",
"办公设备、附件和用品>>办公用品>>测试分类>>荔枝",
"办公设备、附件和用品>>家具用品>>床头用品>>枕头",
"食品、饮料和烟草>>肉和家禽产品>>加工和处理过的肉>>鲜的加工和处理过的肉",
"食品、饮料和烟草>>巧克力、糖、甜品和糖果>>糖果>>口香糖",
"食品、饮料和烟草>>饮料>>咖啡和茶>>咖啡饮料",
"食品、饮料和烟草>>饮料>>非酒精饮料>>泉水和矿泉水",
"办公设备、附件和用品>>办公用品>>书写工具>>水笔",
"造纸原料和纸制品>>纸制品>>个人纸制品>>纸巾",
"食品、饮料和烟草>>巧克力、糖、甜品和糖果>>巧克力、糖和甜品>>巧克力和巧克力代用品",
"食品、饮料和烟草>>饮料>>非酒精饮料>>水",
"食品、饮料和烟草>>乳制品和蛋>>牛奶和黄油产品>>贮藏的牛奶和黄油产品",
"食品、饮料和烟草>>预制食品和罐头>>方便什锦和用品>>方便什锦小吃",
"食品、饮料和烟草>>饮料>>咖啡和茶>>袋茶",
"食品、饮料和烟草>>面包和烘焙食品>>蛋糕、派和糕点>>新鲜蛋糕、派和糕点",
"休闲零食",
"食品、饮料和烟草>>饮料>>咖啡和茶>>非乳场生产的乳品饮料",
"服装、箱包、个人护理用品>>个人护理用品>>洗浴、身体护理品>>化妆品",
"食品、饮料和烟草>>饮料>>非酒精饮料>>软饮料",
"食品、饮料和烟草>>肉和家禽产品>>加工和处理过的肉>>贮藏加工和处理过的肉",
"食品、饮料和烟草>>谷类和豆类制品>>豆类>>豆粉",
"食品、饮料和烟草>>预制食品和罐头>>小吃>>坚果和水果干"
]
// console.log(data)
const treeArr = []
const analysisData = (data) => {
data.forEach(ele => {
const eleArr = ele.split('>>')
judgeData(treeArr, eleArr, 0)
})
}
const judgeData = (treeArr, eleArr, step) => {
if (!treeArr.some(item => {
if (item.value === eleArr[step]) {
return true
}
})) {
const treeSon = {
value: eleArr[step],
lable: eleArr[step]
}
treeArr.push(treeSon)
if (eleArr[step + 1] !== undefined) {
treeSon.children = []
judgeData(treeSon.children, eleArr, step + 1)
}
} else {
treeArr.forEach(ele => {
if (ele.value === eleArr[step]) {
judgeData(ele.children, eleArr, step + 1)
}
})
}
}
analysisData(data)
console.log('treeArr: ', JSON.stringify(treeArr))