解決需求的實際過程記錄——10萬條降雨資料的處理

八叉樹發表於2019-02-28

需求: 師弟讓我幫他處理一個資料,是一個降雨資料,從2015.1.號到2016.12.31號收集的某地區的降雨資料,一共105000條資料,資料格式為csv格式,第一列為編號,第二列為時間,第三列為該時刻的降雨量,資料特徵是如果某段時間的前後都有36個0,則說明這段時間內為一場降雨,我們要做的是求一場降雨的起始時刻以及降雨總量。

解決需求的實際過程記錄——10萬條降雨資料的處理

初次看到資料的時候感覺思路挺清晰的,後來寫的時候發現處處是坑,好多細節需要注意到。先列出採坑記錄:

  • 我用陣列的時候取值和賦值直接通過下標來實現,後來發現這樣還是不行滴,不說經常會出現問題,從寫程式碼的優雅感角度來說這是一種粗暴的方式,所以還是需要一種優雅的方式———定義建構函式

    function Dictionary(){
        this.data = new Array();
        this.put = function(key,value){
            this.data[key] = value;
        };
        this.get = function(key){
            return this.data[key];
        };
        this.size = function(){
            return this.data.length;
        };
    }
    複製程式碼
  • 對於下面的資料應該怎麼取值,開始我是result[0][0].start來獲取start的值,但是發現這種方式是錯誤的,正確的方式應該是result[0].start,即這樣理解:result是一個一維陣列,而不是二維陣列,陣列的每個元素是一個json元素

var result=[ [ start: '201501131150',
    end: '201501140950',
    sum: 15.599999999999984 ],
  [ start: '201501250430',
    end: '201501250910',
    sum: 1.4000000000000004 ],
  [ start: '201501262230',
    end: '201501270330',
    sum: 1.2000000000000002 ],
  [ start: '201501271320',
    end: '201501272050',
    sum: 1.0999999999999999 ],
  [ start: '201501281030',
    end: '201501290050',
    sum: 2.800000000000001 ]
 ]
複製程式碼

所以我的理解是上面的result與下面的result等價

var result=[ { start: '201501131150',
    end: '201501140950',
    sum: 15.599999999999984 },
  { start: '201501250430',
    end: '201501250910',
    sum: 1.4000000000000004 },
  { start: '201501262230',
    end: '201501270330',
    sum: 1.2000000000000002 },
  {start: '201501271320',
    end: '201501272050',
    sum: 1.0999999999999999 },
  { start: '201501281030',
    end: '201501290050',
    sum: 2.800000000000001 }
 ]
複製程式碼
  • 檔案的讀寫操作,想把最後的結果類似上面的result格式寫入到TXT檔案中,剛開始用fs.writeFile方法,發現怎麼寫都不行,即時把result轉換成字串再寫入都不行,要麼獲取到空的陣列,要麼獲取到的全是逗號。後來想到:用迴圈來做吧,每次將陣列裡的一個json物件輸出到TXT檔案,注意這裡用Buffer轉換每次的數成二進位制的再寫入到檔案中

            var chunks=[];
            var length=0;
            result.forEach((item,index)=>{
                var start=item.start;
                var end=item.end;
                var sum=item.sum;
                var value=start+" "+end+" "+sum+" "+'\r\n';
                var buffer=new Buffer(value);
                chunks.push(buffer);
                length+=buffer.length;
                })
            var resultBuffer = new Buffer(length);
            for(var i=0,size=chunks.length,pos=0;i<size;i++){
                chunks[i].copy(resultBuffer,pos);
                pos+=chunks[i].length;
            }
            fs.writeFile('./result.txt',resultBuffer,function(err){
                if(err) throw err;
                console.log('write JSON into TEXT');
            });
    複製程式碼
  • 有一個問題要考慮的是如果一場降雨前面0的個數大於36的話,那麼這隻能算作一場降雨,如果不加其他約束條件的話前面有38個0的時候會算成3場雨的,所以我們需要當前面已經連續36個零的時候第第37個數不能為零(原諒我直接這麼暴力的寫,因為36個真的不算太多)

    if (data[i][1] == 0 && data[i + 1][1] == 0 && data[i + 2][1] == 0 && data[i + 3][1] == 0 && data[i + 4][1] == 0 && data[i + 5][1] == 0&&
                data[i+6][1] == 0 && data[i + 7][1] == 0 && data[i + 8][1] == 0 && data[i + 9][1] == 0 && data[i + 10][1] == 0 && data[i +11][1] == 0&&
                data[i+12][1] == 0 && data[i + 13][1] == 0 && data[i + 14][1] == 0 && data[i + 15][1] == 0 && data[i + 16][1] == 0 && data[i + 17][1] == 0&&
                data[i+18][1] == 0 && data[i + 19][1] == 0 && data[i + 20][1] == 0 && data[i + 21][1] == 0 && data[i + 22][1] == 0 && data[i + 23][1] == 0&&
                data[i+24][1] == 0 && data[i + 25][1] == 0 && data[i + 26][1] == 0 && data[i + 27][1] == 0 && data[i + 28][1] == 0 && data[i + 29][1] == 0&&
                data[i+30][1] == 0 && data[i + 31][1] == 0 && data[i + 32][1] == 0 && data[i + 33][1] == 0 && data[i + 34][1] == 0 && data[i + 35][1] == 0&&
                data[i+36][1]!=0)
    複製程式碼
  • 還有一個問題是如果到了資料的最後一個數時就不用判斷後面還要36個0了,只需要判斷前面有36個零就ok了,所以這裡也要考慮到這個情況

     if ((data[j][1] == 0 && data[j + 1][1] == 0 && data[j + 2][1] == 0 && data[j + 3][1] == 0 && data[j + 4][1] == 0 && data[j + 5][1] == 0&&
                            data[j+6][1] == 0 && data[j + 7][1] == 0 && data[j+ 8][1] == 0 && data[j + 9][1] == 0 && data[j + 10][1] == 0 && data[j +11][1] == 0&&
                            data[j+12][1] == 0 && data[j + 13][1] == 0 && data[j+ 14][1] == 0 && data[j + 15][1] == 0 && data[j + 16][1] == 0 && data[j + 17][1] == 0&&
                            data[j+18][1] == 0 && data[j + 19][1] == 0 && data[j + 20][1] == 0 && data[j+ 21][1] == 0 && data[j + 22][1] == 0 && data[j + 23][1] == 0&&
                            data[j+24][1] == 0 && data[j + 25][1] == 0 && data[j + 26][1] == 0 && data[j + 27][1] == 0 && data[j + 28][1] == 0 && data[j + 29][1] == 0&&
                            data[j+30][1] == 0 && data[j + 31][1] == 0 && data[j + 32][1] == 0 && data[j + 33][1] == 0 && data[j + 34][1] == 0 && data[j + 35][1] == 0)
                            ||j==data.length-1 )
    複製程式碼
  • 最後要注意的是寫入到TXT檔案中時字串後面加上“\r\n"才能換行,這樣我們直接點開TXT檔案看到的才是經過換行的資料,如果是在字串後面加上”\n"那麼我們用編輯器開啟TXT檔案確實看到的也是換行後的資料,但是這時直接開啟TXT檔案看到的資料並沒有換行,所以這點也要注意

     var value=start+" "+end+" "+sum+" "+'\r\n';
    複製程式碼

    最後我們來看看得到的結果txt檔案,大功告成!

解決需求的實際過程記錄——10萬條降雨資料的處理


原始碼:

var fs = require("fs");

fs.readFile('./test.csv', function (err, data) {
    var table = new Array();
    if (err) {
        console.log(err.stack);
        return;
    }
    ConvertToTable(data, function (table) {
        var cont=[];
        var result=[]
        transform(table,cont);
        console.log("**************************************************")
        cont.forEach((item,index)=>{
            result[index]=item.data;
        })
        console.log(result)
        var chunks=[];
        var length=0;
        result.forEach((item,index)=>{
            var start=item.start;
            var end=item.end;
            var sum=item.sum;
            var value=start+" "+end+" "+sum+" "+'\r\n';
            var buffer=new Buffer(value);
            chunks.push(buffer);
            length+=buffer.length;
            })
        var resultBuffer = new Buffer(length);
        for(var i=0,size=chunks.length,pos=0;i<size;i++){
            chunks[i].copy(resultBuffer,pos);
            pos+=chunks[i].length;
        }
        fs.writeFile('./result.txt',resultBuffer,function(err){
            if(err) throw err;
            console.log('write JSON into TEXT');
        });

    console.log("程式執行完畢");
})
})


function ConvertToTable(data, callBack) {
    data = data.toString();
    var table = new Array();
    var rows = new Array();
    rows = data.split("\r\n");
    for (var i = 0; i < rows.length; i++) {
        table.push(rows[i].split(","));
    }

    callBack(table);
}

function transform(data,cont) {
    var k = 0;

    for (var i = 0; i < data.length; i++) {
        var list = new Dictionary();
        if (data[i][1] == 0 && data[i + 1][1] == 0 && data[i + 2][1] == 0 && data[i + 3][1] == 0 && data[i + 4][1] == 0 && data[i + 5][1] == 0&&
            data[i+6][1] == 0 && data[i + 7][1] == 0 && data[i + 8][1] == 0 && data[i + 9][1] == 0 && data[i + 10][1] == 0 && data[i +11][1] == 0&&
            data[i+12][1] == 0 && data[i + 13][1] == 0 && data[i + 14][1] == 0 && data[i + 15][1] == 0 && data[i + 16][1] == 0 && data[i + 17][1] == 0&&
            data[i+18][1] == 0 && data[i + 19][1] == 0 && data[i + 20][1] == 0 && data[i + 21][1] == 0 && data[i + 22][1] == 0 && data[i + 23][1] == 0&&
            data[i+24][1] == 0 && data[i + 25][1] == 0 && data[i + 26][1] == 0 && data[i + 27][1] == 0 && data[i + 28][1] == 0 && data[i + 29][1] == 0&&
            data[i+30][1] == 0 && data[i + 31][1] == 0 && data[i + 32][1] == 0 && data[i + 33][1] == 0 && data[i + 34][1] == 0 && data[i + 35][1] == 0&&
            data[i+36][1]!=0) {
            if((i+37)<=data.length) {
                for (var j = (i + 37); j <data.length; j++) {
                    if ((data[j][1] == 0 && data[j + 1][1] == 0 && data[j + 2][1] == 0 && data[j + 3][1] == 0 && data[j + 4][1] == 0 && data[j + 5][1] == 0&&
                        data[j+6][1] == 0 && data[j + 7][1] == 0 && data[j+ 8][1] == 0 && data[j + 9][1] == 0 && data[j + 10][1] == 0 && data[j +11][1] == 0&&
                        data[j+12][1] == 0 && data[j + 13][1] == 0 && data[j+ 14][1] == 0 && data[j + 15][1] == 0 && data[j + 16][1] == 0 && data[j + 17][1] == 0&&
                        data[j+18][1] == 0 && data[j + 19][1] == 0 && data[j + 20][1] == 0 && data[j+ 21][1] == 0 && data[j + 22][1] == 0 && data[j + 23][1] == 0&&
                        data[j+24][1] == 0 && data[j + 25][1] == 0 && data[j + 26][1] == 0 && data[j + 27][1] == 0 && data[j + 28][1] == 0 && data[j + 29][1] == 0&&
                        data[j+30][1] == 0 && data[j + 31][1] == 0 && data[j + 32][1] == 0 && data[j + 33][1] == 0 && data[j + 34][1] == 0 && data[j + 35][1] == 0)
                        ||j==data.length-1 ){
                        list.put("start", data[i + 36][0]);
                        list.put("end", data[j - 1][0]);
                        var temp = 0;
                        for (var n = i + 36; n <= j - 1; n++) {
                            temp = temp + Number(data[n][1]);
                        }
                        list.put("sum", temp);
                        break;
                    }
                }
                cont[k++] = list;
            }

        }
    }

}

function Dictionary(){
    this.data = new Array();
    this.put = function(key,value){
        this.data[key] = value;
    };
    this.get = function(key){
        return this.data[key];
    };
    this.size = function(){
        return this.data.length;
    };
}


複製程式碼

相關文章