1..数组内多个版本号中找出版本号最高的一项
var versionNo = ['2.1.4.5','3.1.5','3.1.0.6','2.2','1.9.9'];
2..找出字符串中出现频率最高的字符
var = str = "a,b,c,d,e,f,g,a,b,c,a,a,b,b,a,a,t"
1..数组内多个版本号中找出版本号最高的一项
var versionNo = ['2.1.4.5','3.1.5','3.1.0.6','2.2','1.9.9'];
2..找出字符串中出现频率最高的字符
var = str = "a,b,c,d,e,f,g,a,b,c,a,a,b,b,a,a,t"
第一题
versionNo.reduce((pre, item) => {
let pres = pre.split('.')
let items = item.split('.')
let i = 0
while(pres[i] !== undefined && items[i] !== undefined){
if(pres[i] == items[i]){
i++
}else{
return Number(pres[i]) > Number(items[i]) ? pre : item
}
}
return items.length > pres.length ? item : pre
})
第二题
str.split(',').reduce((o, item) => {
o[item] = ~~o[item] + 1
if(o[item] > o._max){
o._max = o[item]
o._maxs = item
}
return o
}, {_max: 0, _maxs: ''})._maxs
我也来一发第一题吧:
const versionNo = ['2.1.4.5', '3.1.5', '3.1.0.6', '2.20', '1.9.9'];
function getLatestVersion(versions) {
return versions
.map((ver) => {
return {
original: ver,
next: ver
.split('.')
.map((v) => v.padStart(2, '0'))
.join('')
.padEnd(8, 0),
};
})
.sort((a, b) => a.next.localeCompare(b.next))
.reverse()[0].original;
}
const latest = getLatestVersion(versionNo);
console.log(latest); // 3.1.5
我寻思着第一题不就是一个 sort()[0]
的事儿?
const max = arr => {
const v = s => s.match(/\d+/g).reduce((p, c) => p * 255 + +c)
return arr.sort((a, b) => v(b) - v(a))[0]
}
何必还转过去转过来呢?
function maxVersion(versions) {
return versions.sort((a, b) => {
const v1 = a.split('.');
const v2 = b.split('.');
for (let i = 0; i < v1.length; i += 1) {
// 如果 v2[i] 为 undefined,那么 v1 更大
if (v2[i] === undefined) {
return -1;
}
if (v1[i] === v2[i]) {
// 版本一致
continue
} else if (v1[i] > v2[i]) {
return -1;
} else {
return 1
}
}
return 0;
})[0];
}
// 考虑到有可能出现频率一样,所以返回的数组
function maxChars(text) {
// 得到不同字符的次数
const o = text.split(',').reduce((a, b) => ({ ...a, [b]: (a[b] || 0) + 1}), {});
// 直接取得出现频率最高的资源的字符
return Object.keys(o).filter(k => o[k] === Math.max(...Object.keys(o).map(k => o[k])))
}
第二题和大家想法差不多,但是第一题我之前都是这么直接判断的
var versionNo = ['2.1.4.5','3.1.5','3.1.0.6','2.2','1.9.9'];
var max = '0.0.0.0';
versionNo.forEach(e => {
if (e > max) {
max = e
}
});
console.log(max);
第二题
function findMax (str) {
let max = 0, obj;
str.split(',').reduce((pre, next) => {
if (next in pre) {
pre[next]++
if (pre[next] > max) {
max = pre[next]
obj = next
}
} else {
pre[next] = 1
}
return pre
}, {})
return obj
}
console.log(findMax(str));
第一题
/**
* 解题思路
* 1.直接遍历数组,按字典序比较字符串,筛选最大值
*/
var arr = ['2.1.4.5', '3.1.5', '3.1.0.6', '2.2', '1.9.9']
let max = ''
arr.forEach((item) => {
if (max < item) {
max = item
}
})
console.log(max)
第二题
/**
* 解题思路
* 1.将字符串转换为数据
* 2.将数组按字典序排序
* 3.遍历数组,记录当前字符遍历次数
* 4.收集遍历次数最多的一个为出现次数最多的字符
*/
var str = 'a,b,c,d,e,f,g,a,b,c,a,a,b,b,a,a,t'
var arr = str.split(',')
arr.sort()
let maxCount = 0
let maxLetter = ''
let curCount = 0
let curLetter = ''
arr.forEach((letter) => {
if (curLetter != letter) {
curLetter = letter
curCount = 0
}
curCount++
if (maxCount < curCount) {
maxCount = curCount
maxLetter = curLetter
}
})
console.log(maxCount, maxLetter)
第一题:(补0逻辑已完善)
单段补全成长度最长的number(1.2.31.4 ->100200031400),然后拼接起来比数字就是了,同时还要考虑版本号是从大到小的,长度再长,首位不够格就够不上老大。
默认首位的最大的版本,后面依次是二级版本,三级版本...以此类推
默认单段版本号最长到4位,可传参进行修改
function getMaxVersion(arr: string[], maxVersionPieceLen = 4) {
const version2Number = (version: string[]) => Number(version.map(_ => `${Array(maxVersionPieceLen - `${_}`.length).fill("0").join("")}${_}`).join(""))
return arr.reduce((pre, cur, index) => {
const curVersion = cur.split('.');
const preVersion = pre.split('.');
//首位大直接return
if (Number(curVersion[0]) > Number(preVersion[0])) {
return cur;
}
//转数字比较,默认单段最大4位,可根据需要传参
return version2Number(curVersion) > version2Number(preVersion) ? cur : pre;
}, arr[0])
}
第二题:
转成map/Object,key为字符串名,value为key的计数,统计完后转entry遍历下即可
8 回答4.8k 阅读✓ 已解决
6 回答3.5k 阅读✓ 已解决
5 回答2.9k 阅读✓ 已解决
6 回答2.4k 阅读
5 回答6.4k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
解决第一个问题
解决第一个问题是在找到所有元素中最大的一个,这里需要明确:
初步想法
因为版本号都是数字,如果能把版本号的各段组合成一个大整数,那就可以使用
Math.max()
来找最大值,同时解决上述两个问题。要组成最大整数,需要一些限制:255
这样的话,4 段 8-bit 版本号正好可以通过位运算组成 32-bit 整数。(题上没给条件,所以如果实际不符合上述条件,就不能采用这种方法。)
先写个把版本号转成整数的函数(当然可以直接在大过程中写代码,不过基于模块化的思想,写个函数来干这件事比较好)
版本号转成整数之后可以用
Math.max()
找出来最大的现在的问题是,拿到的是一个数,而不是版本字符串,还得转换回来……倒是也不难
有了两个工具函数,找最大版本号的函数就是:
更进一步
把版本转成数字也就算了,拿到之后还要转回来,很伤。可以不转不?
如果有一个函数,可以从一个对象按条件进行查找就好了。这个函数当然可以用循环或者
reduce
自己写,不过 Lodash 中有现成的叫_.maxBy()
,不妨直接拿来用解除限制
上面的算法都是基于一开始提出来的两个约束。如果不想受此约束,是否可以用
.maxBy()
来实现呢?.maxBy()
需要从对象中找到一个数值来进行比较,但是我们的版本号需要分段多次比较,显然.maxBy()
不行,得自己写比较算法。思路是写一个
compareVersion(a, b)
,如果a
小于b
,返回-1
,大于返回1
,等于返回0
。考虑到有段长不一样的情况,用0
补足来进行比较(当然也可以不补足,直接按长度判断,代码略复杂一些)。下面的
compareVersion()
比较的是两个数组,也就是像"3.1.5".split(".")
之后的结果。不直接比较版本字符串,是想把拆分这一步放前面,避免每次比较都要先进行一次拆分,减少重复劳动。然后就是常规的循环找最大值了
第二个问题
第二个问题的解决办法也很多,最直接的想法就是写个 map 来计数:
上面的处理办法易懂,但是至少需要遍历两次,可以压缩到一次遍历中
当然也可以用一个
reduce()
来解决