Awk 消除完全重叠的间隔或范围

Awk 消除完全重叠的间隔或范围,awk,Awk,今天早些时候,我看到了一个——显然格式不好,因此已经被删除了——关于删除重叠区间(或范围,从此以后的区间)的问题。问题是如何删除完全在其他间隔内的间隔。例如,我们有以下几点: 1-2 2-3 1-3 2-4 或者,如果视觉效果稍微好一点: 1-2 2-3 1---3 2---4 区间1-2和2-3都被删除,因为它们包含在区间1-3中,因此输出为: 1-3 2-4 先验算法可能是检查每个间隔与其他间隔,从而进行O(n2)比较。有人建议在处理之前对源数据进行排序,这个问题还有其他角度吗

今天早些时候,我看到了一个——显然格式不好,因此已经被删除了——关于删除重叠区间(或范围,从此以后的区间)的问题。问题是如何删除完全在其他间隔内的间隔。例如,我们有以下几点:

1-2
2-3
1-3
2-4
或者,如果视觉效果稍微好一点:

1-2
  2-3
1---3
  2---4
区间
1-2
2-3
都被删除,因为它们包含在区间
1-3
中,因此输出为:

1-3
2-4
先验算法可能是检查每个间隔与其他间隔,从而进行O(n2)比较。有人建议在处理之前对源数据进行排序,这个问题还有其他角度吗

明显的案例有(数据排序):


请,如果您在数据或附属标记中发现了好的陷阱或其他情况,请添加它们。

此解决方案希望在处理之前对数据进行排序,正如某人建议的那样:

$ sort -t- -k1n -k2n file  # playin' it safe
1-2
1-3
2-3
2-4
在awk中:

$ cat program.awk
BEGIN { OFS=FS="-" }
{
    if(p=="") {                     # if p is empty, fill it
        p=$0                        # p is the previous record
        next
    }
    split(p,b,"-")                  # p is split to start and end to b[]

    if(b[1] == $1 && b[2] <= $2) {  # since sorting is expected:
        p=$0                        # if starts are equal p line is included or identical
        next                        # so remove it
    }
    else if($2 <= b[2])             # latter is included
        next

    print p                         # no complete overlap, print p 
    p=$0                            # and to the next
}
END { print p }

只要算法具有多项式复杂性,我认为简单的解决方案也可以:

#!/usr/bin/gawk -f

BEGIN {
    FS=OFS="-";
}
{

    arr[NR][1] = $1;
    arr[NR][2] = $2;
}
END {

    for(i in arr) {

        delete_nxt_elem(i);

        if(arr[i][1]!="")
            print arr[i][1],arr[i][2];
    }
}

function delete_nxt_elem(check_indx,   j) {

    for(j in arr) {

        if(j==check_indx)
            continue;

        if(arr[j][1]<=arr[check_indx][1] && arr[j][2]>=arr[check_indx][2])
            delete arr[check_indx];
    }
}
#/usr/bin/gawk-f
开始{
FS=OFS=“-”;
}
{
arr[NR][1]=1元;
arr[NR][2]=2元;
}
结束{
对于(我在arr中){
删除第(i)项;
如果(arr[i][1]!=“”)
打印arr[i][1]、arr[i][2];
}
}
函数删除元素(检查indx,j){
对于(arr中的j){
如果(j==检查indx)
继续;
如果(arr[j][1]=arr[check_indx][2])
删除arr[检查索引];
}
}

您可以通过设置
-F-
排序文件
将按字母顺序排序,这样
10
将排在
2
之前,等等来避免拆分。您需要类似于
排序-t'-'-k1-k2-n文件的东西。检查一下,因为我总是把我的排序参数搞混了,但是你知道你需要对范围的每个部分分别进行数字排序。而且@karakfa是正确的-设置
-F'-'
,并用
$1
替换
a[1]
,等等。我觉得它可以进一步简化,而不需要太多的“下一个”。。。
$ awk -f program.awk <(sort -t- -k1n -k2n file)
1-3
2-4
1-2
  2-3
#!/usr/bin/gawk -f

BEGIN {
    FS=OFS="-";
}
{

    arr[NR][1] = $1;
    arr[NR][2] = $2;
}
END {

    for(i in arr) {

        delete_nxt_elem(i);

        if(arr[i][1]!="")
            print arr[i][1],arr[i][2];
    }
}

function delete_nxt_elem(check_indx,   j) {

    for(j in arr) {

        if(j==check_indx)
            continue;

        if(arr[j][1]<=arr[check_indx][1] && arr[j][2]>=arr[check_indx][2])
            delete arr[check_indx];
    }
}