TW_黑珍珠号_陈祥梅
Frequency Number 需求
一个 Node.js 小程序,它可以处理一段字符串信息,这段字符串信息是由英文单词组成,每两个单词之间有空格,处理结果也为一段字符串,这个字符串应该每行只显示一个单词和它的数量,并且按出现频率倒序排列。
使用TDD编程流程如下:
- Taking 分解
- Jasmine 测试代码
- JavaScript 实现代码
- Nodejs 单元测试
- git 提交管理代码
重复 2 、3、4、 5直至符合题目要求,然后将项目保存到 git 远程仓库。
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() 方法进行分割。
考虑到两种特殊情况:
- String 开始及结束有空格
利用正则先去除前后空格,即String.replace(/(^\s*)|(\s*$)/g,'');
- 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 。
统计频率有两种方法:
- 定义数组
words[]
,利用indexOf()
(存在返回其在数组中位置 index,不存在则返回 -1)方法查找 word[] 数组是否存在此单词:
不存在:则将其单词及频率(初始为1)作为一个 Map 存放到 wordsFrequency[] 数组,单词 words[] 数组中;
在其整个过程每个单词在 word[] 数组中的位置与 wordsFrequency[] 位置相同(即数组下标相同)
存在:将 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[] 数组中,将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 截图
将项目 push 到 git 远程仓库
使用命令
$ git remote add origin https://github.com/chechenxm/FrequencyNumber.git
$ git push -u origin master
git项目地址