文本處理的小訣竅

文本處理的小訣竅

場景描述

  • 原始文本格式:

        pid1 kid1
        pid3 kid1
        pid1 kid2
        pid1 kid3
        pid2 kid3
        pid2 kid4
  • 須要統計的結果:每條pid能夠跟哪幾個kid關聯,最終結果格式:

        pid1 kid1,kid2,kid3
        pid2 kid3,kid4
        pid3 kid1

* 原始文本大概有2億多行php

處理思路

  • 將文本按第一列排序,排序後效果:
    pid1 kid1
    pid1 kid2
    pid1 kid3
    pid2 kid3
    pid2 kid4
    pid3 kid3
  • 將第一列相同的行合併,效果:
    pid1 kid1,kid2,kid3
    pid2 kid3,kid4
    pid3 kid1

具體解決代碼

# sort -k 1 -n src.txt > sort1.txt
    # cat sort1.txt | php -B '
          $pidtmp = 0;
          $kidtmp = array();
      ' -R '
          list($pid, $kid) = explode("\t", $argn);
          if($pid != $pidtmp) {
              echo "\n".$pidtmp."\t".implode(",", array_keys($kidtmp));
              $pidtmp = $pid;
              $kidtmp = array();
          }
          $kidtmp[$kid] = 1;
      '

以上兩條命令可實現需求,共耗時半個小時左右html

其它說明

本需求中存在一個原始文檔,這個文檔是經過其它程序生成的。那麼存在一個疑問,爲何其它程序生成文檔時,不直接生成所須要的格式(即以上示例的最終格式),而是生成一箇中間格式的文檔。mysql

 

其實在設計以前的程序時,確實就是指望直接輸出以上的最終文檔,但出現一個問題就是這個最終文檔要怎麼存儲,存mysql仍是nosql。嘗試過mysql,一共有2億行結果,每一行就須要讀、寫一次mysql,時間成本過高。而後也嘗試了redis,使用列表存儲,每一行原數據,只須要寫一次redis的列表,能夠減小一次讀,然而時間仍是太長,因此纔將中間結果輸入到文本。再使用以上提到的2條命令將結果轉換爲最終格式,時間成本大下降。redis

 

若是有另一個程序須要根據pid來搜索以上生成的最終文檔,能夠借鑑另外一篇文章 ,入口sql

相關文章
相關標籤/搜索