Узнайте диапазон для каждого поля в столбце - PullRequest
0 голосов
/ 06 июня 2019

У меня есть столбец, который выглядит так:

A 1
B 3
C 5
D 4
E 7
F 1
G 1
H 3

Для каждого поля в столбце № 2 я хочу вычислить диапазон (max-min) радиуса поля 3 вверх и вниз.

A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)

Как это можно сделать в awk?

Я мог бы сделать то же самое в Perl, используя:

my $set_size = @values;
for ( my $i = 0 ; $i < $set_size ; $i++ ) {
    my $min = $i - 4;
    if ( $min < 0 ) { $min = 0; }
    my $max = $i + 4;
    if ( $max > ( $set_size - 1 ) ) { $max = $set_size - 1; }
    my $min_val = $values[$min];
    my $max_val = $values[$min];
    for ( my $j = $min ; $j <= $max ; $j++ ) {
        if ( $values[$j] <= $min_val ) { $min_val = $values[$j]; }
        if ( $values[$j] >= $max_val ) { $max_val = $values[$j]; }
    }
    my $range = $max_val - $min_val;
    printf "$points[$i] %.15f\n", $range;
}

Ответы [ 4 ]

0 голосов
/ 06 июня 2019

Поскольку вы пометили :

#!/usr/bin/env tclsh

lassign $argv file size

set fh [open $file r]
# assume exactly 2 space-separated words per line
set data [dict create {*}[split [read -nonewline $fh]]]
close $fh

set len [dict size $data]
set values [dict values $data]
set i 0

dict for {key _} $data {
    set first [expr {max($i - $size, 0)}]
    set last  [expr {min($i + $size, $len)}]
    puts [format "%s range(%s%s)" \
        $key \
        [string repeat "  " $first] \
        [lrange $values $first $last] \
    ]
    incr i
}

выходы

A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)
0 голосов
/ 06 июня 2019

idk именно то, что означает I want to calculate the range (max-min) of 3 field radius up and down., но чтобы получить вывод, который вы опубликовали из введенного вами, было бы:

$ cat tst.awk
{
    keys[NR] = $1
    values[NR] = $2
}
END {
    range = 3
    for (i=1; i<=NR; i++) {
        min = ( (i - range) >= 1  ? i - range : 1  )
        max = ( (i + range) <= NR ? i + range : NR )
        printf "%s range(", keys[i]
        for (j=min; j<=max; j++) {
            printf "%s%s", values[j], (j<max ? " " : ")\n")
        }
    }
}
$
$ awk -f tst.awk file
A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(3 5 4 7 1 1 3)
F range(5 4 7 1 1 3)
G range(4 7 1 1 3)
H range(7 1 1 3)
0 голосов
/ 06 июня 2019

Ваш пример Perl не распечатывает ваш пример вывода, похоже, он делает что-то другое ... так вот как я бы это сделал в Perl:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use List::Util qw/min max/;

my (@col1, @col2);
while (<>) {
    chomp;
    my ($v1, $v2) = split;
    push @col1, $v1;
    push @col2, $v2;
}

my @prefix;
for my $i (0 .. $#col1) {
    my @range = @col2[max($i - 3, 0) .. min($i + 3, $#col2)];
    push @prefix, ' ' if $i > 3;
    unshift @range, @prefix;
    say "$col1[$i] range(@range)"
}

работает:

$ perl range.pl input.txt
A range(1 3 5 4)
B range(1 3 5 4 7)
C range(1 3 5 4 7 1)
D range(1 3 5 4 7 1 1)
E range(  3 5 4 7 1 1 3)
F range(    5 4 7 1 1 3)
G range(      4 7 1 1 3)
H range(        7 1 1 3)

Форматирование прервется, если какое-либо из чисел будет больше 9.

0 голосов
/ 06 июня 2019

TXR в приглашении оболочки:

bash$ txr -c '@(collect)
@label @num
@(end)
@(bind rng @[window-map 3 nil (opip list (remq nil) (mapcar toint)) num])
@(output)
@  (repeat)
@label range(@rng) -> @(find-min rng)..@(find-max rng) 
@  (end)
@(end)' 
A 1
B 3
C 5
D 4
E 7
F 1
G 1
H 3
[Ctrl-D][Enter]
A range(1 3 5 4) -> 1..5 
B range(1 3 5 4 7) -> 1..7 
C range(1 3 5 4 7 1) -> 1..7 
D range(1 3 5 4 7 1 1) -> 1..7 
E range(3 5 4 7 1 1 3) -> 1..7 
F range(5 4 7 1 1 3) -> 1..7 
G range(4 7 1 1 3) -> 1..7 
H range(7 1 1 3) -> 1..7 
...