斗胆来评价一下诸位大神的答案。。。
var o = [].reduce.call('cbaacfdeaebb',function(p,n){
return p[n] = (p[n] || 0) + 1,p;
},{}),
s = Object.keys(o).reduce(function(p,n){
return o[p] <= o[n] ? p : n;
});
console.log(s,o[s]);
正统的Hash Table思路。缺点是Object.keys()不能保证顺序,所以存在风险。
const all = "cbaacfdeaebb".split("")
.reduce((all, ch, i) => {
const m = all[ch] || (all[ch] = { ch: ch, index: i, count: 0 });
m.count++;
return all;
}, {});
const theOne = Object.keys(all)
.map(ch => all[ch])
.reduce((min, t) => min.count === t.count
? (min.index > t.index ? t : min)
: (min.count > t.count ? t : min));
console.log(`${theOne.ch}: ${theOne.count}`);
引入了index来解决顺序问题,比较健康和简练。
function findFirstChar(string) {
const desc = [];
[...string].forEach((char, index) => {
const item = desc.find(item => item.char === char)
item ? item.count++ : desc.push({ char, index, count: 1 })
})
return desc.sort((a, b) => a.count - b.count)[0]
}
利用数组代替Hash Table,解决了顺序问题,思路不错。
但是Array.sort()并不一定是stable的,这个造成的风险更大。
const less = (x, y) => x.count <= y.count && x.first < y.first
function firstSingle (string) {
let map = {}
string.split('')
.forEach((char, index) => {
if (map[char])
map[char].count++
else
map[char] = { count: 1, first: index, char }
})
return Object.values(map).reduce((x, y) => less(x, y) ? x : y).char
}
思路相似,利用Hash Table,并引入了index解决顺序问题。
ES2017还没有正式发布,Object.values
目前还是草案。
另外原谅我强迫症重新排个版:
const less = (x, y) => (x.count <= y.count && x.first < y.first) ? x : y;
function firstSingle (string) {
let map = {}
string.split('')
.forEach((char, index) => {
map[char] ? map[char].count++ : map[char] = { count: 1, first: index, char }
});
return Object.values(map).reduce(less).char
}
最后是我的two cents:
var str = "cbaacfdeaebb";
var result = [...new Set(str)]
.map(el => ({el, len: str.split(el).length}))
.reduce((a,e) => (a.len > e.len ? e : a))
.el;