亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: split內(nèi)存占用太大怎么辦 [打印本頁(yè)]

作者: raoweijian    時(shí)間: 2013-11-14 19:52
標(biāo)題: split內(nèi)存占用太大怎么辦
現(xiàn)在有圖1所示文件,包含了數(shù)百萬(wàn)個(gè)位點(diǎn)的信息,相互之間用空格分開(kāi)。
現(xiàn)在需要找出指定開(kāi)始和終止位置之間的信息,統(tǒng)計(jì)有多少是大于3的。
比如需要統(tǒng)計(jì)第3000-5000個(gè)位點(diǎn)內(nèi),有多少個(gè)位點(diǎn)的數(shù)字是大于3.
如果用split,內(nèi)存會(huì)飆到十多G,不適用。substr也不好用,因?yàn)槿绻麛?shù)字為兩位數(shù)或者三位數(shù),則會(huì)占用多個(gè)字符位置,沒(méi)辦法統(tǒng)計(jì)。
請(qǐng)問(wèn)應(yīng)該怎么解決這個(gè)問(wèn)題?

1.jpg (177.82 KB, 下載次數(shù): 103)

圖1

圖1

作者: rubyish    時(shí)間: 2013-11-15 01:18
本帖最后由 rubyish 于 2013-11-14 21:19 編輯

example:
  1. #!/usr/bin/perl

  2. my $data = '0 0 0 1 2 3 4 5 6 7 8 1 1 1 11 15 16 0 0 0 0 12';
  3. my ( $begin, $end, $num, $count ) = ( 5, 15, 3, 0 );
  4. my ( $L1, $L2 ) = ( $begin - 1, $end - $begin + 1 );
  5. my ($wanted) = $data =~ /^(?:\S+\s+){$L1}((?:\S+\s+){$L2})/;

  6. $& > $num and $count++ while $wanted =~ /\S+/g;
  7. print "P$begin ~ P$end [ data > $num ] count = $count\n";
復(fù)制代碼

作者: q1208c    時(shí)間: 2013-11-15 08:36
回復(fù) 1# raoweijian

不是太清楚樓主的數(shù)據(jù)是來(lái)自文件還是哪里. 另外, 數(shù)據(jù)的總量有多大.

如果數(shù)據(jù)能讀入內(nèi)存(全部或一行), 可以使用split, 不過(guò), 要加個(gè)參數(shù), 類(lèi)似

  1. my $others = $data;
  2. my ($first, $others) = split(/\s+/, $others, 2);
復(fù)制代碼
這樣, 你的數(shù)據(jù)會(huì)分成兩部分, 前一部分只有一個(gè)數(shù)字, 所有的其它的數(shù)據(jù)都在另一部分, 這樣, 占用的內(nèi)存應(yīng)該不是太大. 然后, 繼續(xù)split下去就行了. 每次只處理一個(gè)數(shù)據(jù).
   
作者: jason680    時(shí)間: 2013-11-15 10:11
本帖最后由 jason680 于 2013-11-15 10:22 編輯

回復(fù) 1# raoweijian

How about this example ...
Note: you can control them by yourself

$ cat get_long_string.pl
#!/usr/bin/perl
use strict;
use warnings;

$_="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80";

my $sCnt = 1;
my $sOut = "";
while(m/((?:\S+\s+){10})/g){ # 10 items for one times
  if(31 <= $sCnt && $sCnt <= 50){
    $sOut .= $1
  }
  $sCnt +=10;   # 10 items for one times
}
print "Out=$sOut\n";

$ perl get_long_string.pl
Out=31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
   
作者: kk861123    時(shí)間: 2013-11-15 11:30
try~ set $/:
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. my $str = join(' ' => 1..22);

  5. print $str,"\n";
  6. {
  7.   open my $fh, '<', \$str or die $!;
  8.   local $/=' ';
  9.   while ( <$fh> ) {
  10.     print "$_\n";
  11.   }
  12. }
復(fù)制代碼

作者: afukada    時(shí)間: 2013-11-15 13:28
  1. use strict;
  2. use warnings;

  3. $_="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80";

  4. my ($start,$end,$dataStart,$i)=(31,50,0,0);
  5. my @myList;

  6. while(/\s+/g)
  7. {
  8.         $i++;
  9.         push(@myList,substr($_,$dataStart,pos($_)-$dataStart-1)) if($i>=$start&&$i<=$end);
  10.         $dataStart=pos($_);
  11. }

  12. print join(",",@myList),"\n";
復(fù)制代碼
這個(gè)如何
作者: pitonas    時(shí)間: 2013-11-15 13:44
嘆為觀(guān)止{:2_178:}
作者: raoweijian    時(shí)間: 2013-11-15 14:42
看來(lái)還是我對(duì)正則匹配了解得不夠。這個(gè)數(shù)據(jù)一共有200M,大約3000W個(gè)位點(diǎn),3樓說(shuō)的方法每次處理一個(gè)似乎并不適用。
二樓和四樓都用到了/^(?:\S+\s+){$L1}((?:\S+\s+){$L2})/類(lèi)似這樣的匹配,不過(guò)我不太看得懂。
五樓把默認(rèn)換行符改成了空格,應(yīng)該是可行的,不過(guò)我還沒(méi)具體試過(guò)。
六樓的方法之前沒(méi)用到過(guò),代碼測(cè)試結(jié)果很好,就是while(/\s+/g),這種用法具體表示什么不是很明白。

后來(lái)我自己想了個(gè)辦法,就是每次只讀100個(gè)數(shù)字,然后判斷是否在區(qū)間內(nèi),反復(fù)循環(huán),效率也還可以接受。
作者: rubyish    時(shí)間: 2013-11-16 02:17
kk861123 發(fā)表于 2013-11-15 07:30
try~ set $/:
  1. local $/=' ';
復(fù)制代碼


學(xué)習(xí)了!這個(gè)速度應(yīng)該比較快。




歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2