多个数据的展开与压缩

在开发中,遇到一个需求,需要将一组数据,将连续出现的部分压缩成 n*y 的形式,比如:20 30 30 20 压缩后的结果应为 20 2x30 20

同时也要对压缩的数据进行解压还原。

压缩数据算法实现:

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
/**
* 将数组数中相同的元素进行合并,表示成 数量*值 的形式,元素之间使用逗号分隔
* @param {*} arr
* @return 返回的是数组
*/
export function compressArray(arr, productSign = 'x') {
if (!Array.isArray(arr)) return arr

const result = []
let count = 1

for (let i = 0; i < arr.length; i++) {
// 如果是最后一个元素或者当前元素与下一个元素不同
if (i === arr.length - 1 || arr[i] !== arr[i + 1]) {
// 如果连续出现的元素个数大于 1,则将其压缩为数量*值的形式
if (count > 1) {
result.push(count + productSign + arr[i])
}
// 否则直接将当前元素加入结果数组中
else {
result.push(arr[i])
}
// 将计数器重置为 1
count = 1
}
// 如果当前元素与下一个元素相同,则将计数器加 1
else {
count++
}
}

return result
}

// 测试
compressArray([20,30,30,20]) // 结果:[20,"2*30",20]

解压数据算法实现:

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
/**
* 将字符串分隔符统一成逗号
* @param {*} str
* @param {*} returnString 是否转换成字符串返回
* @param {*} separator
* @returns
*/
export function formatStringToArray(str, returnString = false, separator = ',') {
let results = []
if (typeof str !== 'string') results = [str]
else {
// 先通过字符串进行分割
results = str.split(/,|:|;|\s+|,|;|。|\-|~|\+/)
}

// 判断每个元素是否包含 *、x、X, 如果包含,则进行展开
const newResults = []
const regex = /(\d+)([xX*])(\d+)/
results.forEach(item => {
const match = item.match(regex)
if (match) {
const count = parseInt(match[1], 10)
const value = parseInt(match[3], 10)
for (let i = 0; i < count; i++) {
newResults.push(value)
}
} else {
newResults.push(item)
}
})
if (returnString) return newResults.join(separator)
return newResults
}

// 测试
formatStringToArray("20 2*30 20") // 结果:['20','30','30','20']
formatStringToArray("20 2*30 20",true) // 结果:"20,30,30,20"