Frequency Number

TW_黑珍珠号_陈祥梅

Frequency Number 需求

一个 Node.js 小程序,它可以处理一段字符串信息,这段字符串信息是由英文单词组成,每两个单词之间有空格,处理结果也为一段字符串,这个字符串应该每行只显示一个单词和它的数量,并且按出现频率倒序排列。

使用TDD编程流程如下:

  1. Taking 分解
  2. Jasmine 测试代码
  3. JavaScript 实现代码
  4. Nodejs 单元测试
  5. git 提交管理代码

重复 2 、3、4、 5直至符合题目要求,然后将项目保存到 git 远程仓库。


Tasking 分解图

Frequency Number_第1张图片
FrequencyNumber Tasking 分解

代码模块及测试用例

测试用例
输入 输出
it it 1
it will it 1 will 1
it will be it will 1 be 1 it 2
it [多个空格] will it will 1 it 2
主函数

实现代码如下

function main(String){
    if(String === '')
        return String;
    let wordsString = splitString(String);
    let wordsFrequency = countFreqy(wordsString);
    let result = sortFrequency(wordsFrequency);
    return format(result);
}

测试代码如下

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 :将一个含有空格的英文单词字符串分解为一个个单词

将传入的字符串 String 用 split() 方法进行分割。
考虑到两种特殊情况:

  1. String 开始及结束有空格
    利用正则先去除前后空格,即 String.replace(/(^\s*)|(\s*$)/g,'');
  2. String 单词中间有空格
    按照多个空格分割单词,即 String.split(/\s+/)

实现代码如下

function splitString(String) {
    String = String.replace(/(^\s*)|(\s*$)/g,'');
    let wordsString = String.split(/\s+/);
    return wordsString;
}

测试代码如下

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 :计算每个单词出现频率

JS 中有类似于 Java 中 Map 键值对(key-value) 的数据结构 Map类,并且同Java一样key值唯一,在此定义了 Map 数组 wordsFrequency[] 用于存放不同单词 word 及它们分别对应的频率 count 。
统计频率有两种方法:

  1. 定义数组 words[] ,利用 indexOf()存在返回其在数组中位置 index,不存在则返回 -1)方法查找 word[] 数组是否存在此单词:
    不存在:则将其单词及频率(初始为1)作为一个 Map 存放到 wordsFrequency[] 数组,单词 words[] 数组中;
    在其整个过程每个单词在 word[] 数组中的位置与 wordsFrequency[] 位置相同(即数组下标相同)
    存在:将 wordsFrequency[] 此位置 (即利用indexof() 求出的index) 的元素中的 count 自加一即可。
  2. 定义 Map wor,利用 Map 中键值唯一,例如
    wor = { key1: 1, key2: 2}
    wor[key1] 值 为 1(因 wor 中 已存在 key 值 key1),
    wor[key3] 值 为 undefined(wor 中不存在 key3)
    以此为单词是否存在于 wordsFrequency[] 的判定条件:
    不存在:将 word 及 count 存入 wordsFrequency[] 数组中,将word作为key存入 wor 中,其值等于此单词在 wordsFrequency[] 数组中位置;
    存在:将 wordFrequency[] 对应单词频率自加一。

两种方法均可实现,按实际情况自行选择即可。

实现代码如下

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 ++ ){
       /* 利用数组作媒介
       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;

测试代码如下

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: 按照单词出现的频率升序排序

此方法利用 JS 中已有的 sort() 方法,自定义按照value值排序的 compare() 函数实现。关于sort()方法语法规则可参考 W3School对sort()的介绍 。

实现代码如下

function compare(property){
    return function(a,b){
        return a[property] - b[property];
    }
}
function sortFrequency(wordsFrequency){
    wordsFrequency.sort(compare('count'));
    return wordsFrequency;
}

测试代码如下

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: 格式化结果,使其符合题目要求

实现代码如下

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;
}

完整代码

完整实现代码如下

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 ++ ){
       /* 利用数组作媒介排序
       if( (index = words.indexOf(wordsString[i])) === -1){
            words.push(wordsString[i]);
            wordsFrequency.push({word: wordsString[i], count: 1});
        }else{
            wordsFrequency[index].count ++;
        }*/

       //利用Json对象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
}


测试代码如下


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 截图

Frequency Number_第2张图片
git log

将项目 push 到 git 远程仓库

使用命令

$ git remote add origin https://github.com/chechenxm/FrequencyNumber.git
$ git push -u origin master

git项目地址

你可能感兴趣的:(Frequency Number)