忘记密码   免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 2809 | 回复: 5

区间合并 [复制链接]

论坛徽章:
0
发表于 2018-05-08 21:53 |显示全部楼层
各位大侠晚上好!
向大家请教:一个文件中有两列,每一行是一个区域,顺序是从上向下递增
start          end
10467        10472
10469        10474
10482        10487
10487        10492
10491        10496
10495        10500
10523        10528
10540        10545
10561        10566
10569        10574
10575        10580

目的:当满足$end-$start(下一行)=1条件时,才合并该区域,如上述所示10492-10491=1,10496-10495=1;
得到最后结果应该是:10487   10500;
麻烦大家了!

论坛徽章:
0
发表于 2018-05-09 11:09 |显示全部楼层
# data input
my $line;
my (@start, @end);
my $i;

while ($line = <>) {
        chomp($line);
        my ($start, $end) = split(/\s+/, $line);
        print "$start\t\t$end\n";
        push @start, $start;
        push @end, $end;
}
print "\n\n";


# data merge
my (@first, @second);

if (@start) {
        push @first, $start[0];
        for ($i=0; $i<$#start; $i++) {
                if ($end[$i] - $start[$i + 1] != 1) {
                        push @second, $end[$i];
                        push @first, $start[$i + 1];
                }
        }
        push @second, $end[-1];
}

# show result
print "\n\n";
for ($i=0; $i<@first; $i++) {
        print "$first[$i]\t\t$second[$i]\n";
}

论坛徽章:
0
发表于 2018-05-10 10:19 |显示全部楼层
回复 2# flywithperl
多谢这位大侠,我也是你这种思路,写的比较坎坷,感谢帮忙!
想了下 另一种思路可以一次读两行进行判断!



论坛徽章:
0
发表于 2018-05-19 16:12 |显示全部楼层
逐行处理
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;

  5. my @stack;
  6. while (<DATA>) {
  7.     my $rec = [split];
  8.     if (@stack) {
  9.         merge(\@stack, $rec);
  10.     } else {
  11.         push @stack, $rec;
  12.     }
  13. }

  14. print "@$_\n" for @stack;
  15. exit 0;

  16. sub merge {
  17.     my ($stack, $new) = @_;
  18.     my $last;
  19.     while (@$stack) {
  20.         $last = pop @$stack;
  21.         if ($last->[1] - $new->[0] == 1) {
  22.             $new = [ $last->[0], $new->[1] ];
  23.         } else {
  24.             push @$stack, $last;
  25.             last;
  26.         }
  27.     }
  28.     push @$stack, $new;
  29. }

  30. __DATA__
  31. 10467        10472
  32. 10469        10474
  33. 10482        10487
  34. 10487        10492
  35. 10491        10496
  36. 10495        10500
  37. 10523        10528
  38. 10540        10545
  39. 10561        10566
  40. 10569        10574
  41. 10575        10580
复制代码

论坛徽章:
0
发表于 2018-05-19 16:12 |显示全部楼层
逐行处理
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;

  5. my @stack;
  6. while (<DATA>) {
  7.     my $rec = [split];
  8.     if (@stack) {
  9.         merge(\@stack, $rec);
  10.     } else {
  11.         push @stack, $rec;
  12.     }
  13. }

  14. print "@$_\n" for @stack;
  15. exit 0;

  16. sub merge {
  17.     my ($stack, $new) = @_;
  18.     my $last;
  19.     while (@$stack) {
  20.         $last = pop @$stack;
  21.         if ($last->[1] - $new->[0] == 1) {
  22.             $new = [ $last->[0], $new->[1] ];
  23.         } else {
  24.             push @$stack, $last;
  25.             last;
  26.         }
  27.     }
  28.     push @$stack, $new;
  29. }

  30. __DATA__
  31. 10467        10472
  32. 10469        10474
  33. 10482        10487
  34. 10487        10492
  35. 10491        10496
  36. 10495        10500
  37. 10523        10528
  38. 10540        10545
  39. 10561        10566
  40. 10569        10574
  41. 10575        10580
复制代码

论坛徽章:
11
子鼠
日期:2014-10-11 16:46:4815-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:532016科比退役纪念章
日期:2018-03-16 10:24:05
发表于 2018-05-19 17:52 |显示全部楼层
本帖最后由 523066680 于 2018-05-19 17:55 编辑

如果数据量不大

  1. use File::Slurp;
  2. STDOUT->autoflush(1);

  3. my $data = read_file( "src.txt" );

  4. $data =~s/(\d+)\n(\d+)\s+/if ($1-$2 == 1) {print "Remove: $1 $2\n"; "";} else { ${&} }/eg;
  5. print $data;
复制代码

Remove: 10492 10491
Remove: 10496 10495
start          end
10467        10472
10469        10474
10482        10487
10487        10500
10523        10528
10540        10545
10561        10566
10569        10574
10575        10580

您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:wangnan@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP