TW_黑珍珠號(hào)_陳祥梅
Frequency Number 需求
一個(gè) Node.js 小程序,它可以處理一段字符串信息穴张,這段字符串信息是由英文單詞組成,每?jī)蓚€(gè)單詞之間有空格找颓,處理結(jié)果也為一段字符串叮贩,這個(gè)字符串應(yīng)該每行只顯示一個(gè)單詞和它的數(shù)量佛析,并且按出現(xiàn)頻率倒序排列寸莫。
使用TDD編程流程如下:
- Taking 分解
- Jasmine 測(cè)試代碼
- JavaScript 實(shí)現(xiàn)代碼
- Nodejs 單元測(cè)試
- git 提交管理代碼
重復(fù) 2 档冬、3、4披坏、 5直至符合題目要求盐数,然后將項(xiàng)目保存到 git 遠(yuǎn)程倉(cāng)庫(kù)。
Tasking 分解圖
代碼模塊及測(cè)試用例
測(cè)試用例
輸入 | 輸出 |
---|---|
it | it 1 |
it will | it 1 will 1 |
it will be it | will 1 be 1 it 2 |
it [多個(gè)空格] will it | will 1 it 2 |
主函數(shù)
實(shí)現(xiàn)代碼如下
function main(String){
if(String === '')
return String;
let wordsString = splitString(String);
let wordsFrequency = countFreqy(wordsString);
let result = sortFrequency(wordsFrequency);
return format(result);
}
測(cè)試代碼如下
describe('test for main',function(){
it('return the result given the string ',function(){
expect(frequencyNumber.main('it')).toEqual('it 1');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main('it will')).toEqual('it 1\r\nwill 1');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main('it will be it ')).toEqual('will 1\r\nbe 1\r\nit 2');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main(' it will it ')).toEqual('will 1\r\nit 2');
});
});
包含代碼模塊如下:
1. split String :將一個(gè)含有空格的英文單詞字符串分解為一個(gè)個(gè)單詞
將傳入的字符串 String 用 split() 方法進(jìn)行分割。
考慮到兩種特殊情況:
- String 開始及結(jié)束有空格
利用正則先去除前后空格攻旦,即String.replace(/(^\s*)|(\s*$)/g,'');
- String 單詞中間有空格
按照多個(gè)空格分割單詞牢屋,即String.split(/\s+/)
實(shí)現(xiàn)代碼如下
function splitString(String) {
String = String.replace(/(^\s*)|(\s*$)/g,'');
let wordsString = String.split(/\s+/);
return wordsString;
}
測(cè)試代碼如下
describe('split String to words', function(){
it('return null given null', function(){
expect(frequencyNumber.splitString('')).toEqual('');
});
it('return one word given one word ', function(){
expect(frequencyNumber.splitString('it')).toEqual(['it']);
});
it('return two word given two word', function(){
expect(frequencyNumber.splitString('it will')).toEqual(['it','will']);
});
it('return three word given three word ', function(){
expect(frequencyNumber.splitString('it will get')).toEqual(['it', 'will', 'get']);
});
it('return two word given two word with some blanks', function(){
expect(frequencyNumber.splitString(' it will ')).toEqual(['it','will']);
});
}
);
2. count frequency :計(jì)算每個(gè)單詞出現(xiàn)頻率
JS 中有類似于 Java 中 Map 鍵值對(duì)(key-value) 的數(shù)據(jù)結(jié)構(gòu) Map類,并且同Java一樣key值唯一,在此定義了 Map 數(shù)組 wordsFrequency[]
用于存放不同單詞 word 及它們分別對(duì)應(yīng)的頻率 count 怀估。
統(tǒng)計(jì)頻率有兩種方法:
- 定義數(shù)組
words[]
,利用indexOf()
(存在返回其在數(shù)組中位置 index,不存在則返回 -1)方法查找 word[] 數(shù)組是否存在此單詞:
不存在:則將其單詞及頻率(初始為1)作為一個(gè) Map 存放到 wordsFrequency[] 數(shù)組康铭,單詞 words[] 數(shù)組中从藤;
在其整個(gè)過程每個(gè)單詞在 word[] 數(shù)組中的位置與 wordsFrequency[] 位置相同(即數(shù)組下標(biāo)相同)
存在:將 wordsFrequency[] 此位置 (即利用indexof() 求出的index) 的元素中的 count 自加一即可锁蠕。 - 定義 Map
wor
荣倾,利用 Map 中鍵值唯一骑丸,例如
wor = { key1: 1, key2: 2}
wor[key1] 值 為 1(因 wor 中 已存在 key 值 key1),
wor[key3] 值 為 undefined(wor 中不存在 key3)
以此為單詞是否存在于wordsFrequency[]
的判定條件:
不存在:將 word 及 count 存入 wordsFrequency[] 數(shù)組中通危,將word作為key存入 wor 中推姻,其值等于此單詞在 wordsFrequency[] 數(shù)組中位置;
存在:將 wordFrequency[] 對(duì)應(yīng)單詞頻率自加一忍燥。
兩種方法均可實(shí)現(xiàn)厂捞,按實(shí)際情況自行選擇即可靡馁。
實(shí)現(xiàn)代碼如下
function countFreqy(wordsString){
var count = new Array;
var words = new Array;
var wordsFrequency = new Array;
var cou;
var wor = {};
var index;
for(var i = 0, len = wordsString.length; i < len; i ++ ){
/* 利用數(shù)組作媒介
if( (index = words.indexOf(wordsString[i])) === -1){
words.push(wordsString[i]);
wordsFrequency.push({word: wordsString[i], count: 1});
}else{
wordsFrequency[index].count ++;
}*/
//利用Map類key值唯一
if(wor[wordsString[i]] === undefined ){
wordsFrequency.push({word: wordsString[i], count:1});
wor[wordsString[i]] = wordsFrequency.length - 1;
}else {
wordsFrequency[wor[wordsString[i]]].count ++;
}
}
return wordsFrequency;
測(cè)試代碼如下
describe('count the Frequency of words',function () {
it ('return one word and its frequency given one word', function () {
expect(frequencyNumber.countFreqy(['it'])).toEqual("it 1");
});
it ('return two word and their own frequency given two different word', function () {
expect(frequencyNumber.countFreqy(['it','is'])).toEqual("it 1\r\nis 1");
});
it ('return one word and their own frequency given two same word', function () {
expect(frequencyNumber.countFreqy(['it','it'])).toEqual("it 2");
});
});
3. sortFrequency: 按照單詞出現(xiàn)的頻率升序排序
此方法利用 JS 中已有的 sort()
方法,自定義按照value值排序的 compare()
函數(shù)實(shí)現(xiàn)。關(guān)于sort()
方法語法規(guī)則可參考 W3School對(duì)sort()的介紹 侠畔。
實(shí)現(xiàn)代碼如下
function compare(property){
return function(a,b){
return a[property] - b[property];
}
}
function sortFrequency(wordsFrequency){
wordsFrequency.sort(compare('count'));
return wordsFrequency;
}
測(cè)試代碼如下
describe ('sort the Frequency of the words',function(){
it('return the result in sequence given the random result',function(){
expect(frequencyNumber.sortFrequency([{word: 'it',count : 2},{word:'will',count:1}])).toEqual("will 1\r\nit 2");
});
it('return the result in sequence given the random result',function(){
expect(frequencyNumber.sortFrequency([{word: 'it',count : 1},{word:'will',count:2},{}])).toEqual("it 1\r\nwill 2");
});
});
4. format: 格式化結(jié)果,使其符合題目要求
實(shí)現(xiàn)代碼如下
function format( wordsFrequency) {
var result = ''
for(var i = 0,len = wordsFrequency.length; i < len; i ++){
if(i > 0){
result += '\r\n';
}
result = result + wordsFrequency[i].word + ' ' + wordsFrequency[i].count;
}
return result;
}
完整代碼
完整實(shí)現(xiàn)代碼如下
function main(String){
if(String === '')
return String;
let wordsString = splitString(String);
let wordsFrequency = countFreqy(wordsString);
let result = sortFrequency(wordsFrequency);
return format(result);
}
function splitString(String) {
String = String.replace(/(^\s*)|(\s*$)/g,'');
let wordsString = String.split(/\s+/);
return wordsString;
}
function countFreqy(wordsString){
let count = new Array;
let words = new Array;
let wordsFrequency = new Array;
let cou;
let wor = {};
let index;
for(var i = 0, len = wordsString.length; i < len; i ++ ){
/* 利用數(shù)組作媒介排序
if( (index = words.indexOf(wordsString[i])) === -1){
words.push(wordsString[i]);
wordsFrequency.push({word: wordsString[i], count: 1});
}else{
wordsFrequency[index].count ++;
}*/
//利用Json對(duì)象key值唯一排序
if(wor[wordsString[i]] === undefined ){
wordsFrequency.push({word: wordsString[i], count:1});
wor[wordsString[i]] = wordsFrequency.length - 1;
}else {
wordsFrequency[wor[wordsString[i]]].count ++;
}
}
return wordsFrequency;
}
function compare(property){
return function(a,b){
return a[property] - b[property];
}
}
function sortFrequency(wordsFrequency){
wordsFrequency.sort(compare('count'));
return wordsFrequency;
}
function format( wordsFrequency) {
let result = '';
for(var i = 0,len = wordsFrequency.length; i < len; i ++){
if(i > 0){
result += '\r\n';
}
result = result + wordsFrequency[i].word + ' ' + wordsFrequency[i].count;
}
return result;
}
module.exports = {
splitString : splitString,
countFreqy : countFreqy,
sortFrequency : sortFrequency,
main: main
}
測(cè)試代碼如下
var frequencyNumber = require('./fn.js')
/*describe('split String to words', function(){
it('return null given null', function(){
expect(frequencyNumber.splitString('')).toEqual('');
});
it('return one word given one word ', function(){
expect(frequencyNumber.splitString('it')).toEqual(['it']);
});
it('return two word given two word', function(){
expect(frequencyNumber.splitString('it will')).toEqual(['it','will']);
});
it('return three word given three word ', function(){
expect(frequencyNumber.splitString('it will get')).toEqual(['it', 'will', 'get']);
});
it('return two word given two word with some blanks', function(){
expect(frequencyNumber.splitString(' it will ')).toEqual(['it','will']);
});
}
);
describe('count the Frequency of words',function () {
it ('return one word and its frequency given one word', function () {
expect(frequencyNumber.countFreqy(['it'])).toEqual("it 1");
});
it ('return two word and their own frequency given two different word', function () {
expect(frequencyNumber.countFreqy(['it','is'])).toEqual("it 1\r\nis 1");
});
it ('return one word and their own frequency given two same word', function () {
expect(frequencyNumber.countFreqy(['it','it'])).toEqual("it 2");
});
});
describe ('sort the Frequency of the words',function(){
it('return the result in sequence given the random result',function(){
expect(frequencyNumber.sortFrequency([{word: 'it',count : 2},{word:'will',count:1}])).toEqual("will 1\r\nit 2");
});
it('return the result in sequence given the random result',function(){
expect(frequencyNumber.sortFrequency([{word: 'it',count : 3},{word:'will',count:2},{word:'is', count: 1}])).toEqual("is 1\r\nwill 2\r\nit 3");
});
});*/
describe('test for main',function(){
it('return the result given the string ',function(){
expect(frequencyNumber.main('it')).toEqual('it 1');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main('it will')).toEqual('it 1\r\nwill 1');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main('it will be it ')).toEqual('will 1\r\nbe 1\r\nit 2');
});
it('return the result given the string ',function(){
expect(frequencyNumber.main(' it will it ')).toEqual('will 1\r\nit 2');
});
});
git log 截圖
將項(xiàng)目 push 到 git 遠(yuǎn)程倉(cāng)庫(kù)
使用命令
$ git remote add origin https://github.com/chechenxm/FrequencyNumber.git
$ git push -u origin master