максимальное и минимальное значение совпадающих строк

Я хотел бы подсчитать минимальное и максимальное значение моей соответствующей строки в файле:

У меня есть:

xxx 5
xxx 0  
xxx 10  
yyy 1  
yyy 5  
yyy 10

И я хотел бы иметь на выходе:

xxx 0 10
yyy 1 10

Минимальное и максимальное значение для совпадений xxx и yyy.

Мой код:

awk '{if(min==""){min=max=$2}
      if($2>max) {max=$2}
      if($2<min) {min=$2}
      n[$1]++}
      END {for (l in n) {print l "\t" min[l] }}' inputfile

Большое спасибо за любую помощь.


person Paul    schedule 07.10.2014    source источник
comment
Так в чем твоя ошибка? Есть ли хотя бы ошибка?   -  person APerson    schedule 07.10.2014


Ответы (1)


Для этого вам нужны массивы:

awk '!($1 in min) {min[$1]=$2; max[$1]=$2}
     {max[$1]=(max[$1]<$2?$2:max[$1])
      min[$1]=(min[$1]>$2?$2:min[$1])}
      END { for (i in max) print i, min[i], max[i]}' file

Объяснение

max[] содержит максимальное значение для каждого значения. То же самое относится и к min[].

  • !($1 in min) {min[$1]=$2; max[$1]=$2} если нет min для текущего поля, инициализировать их.
  • max[$1]=(max[$1]<$2?$2:max[$1]) если текущее 2-е поле больше, чем соответствующий максимум для 1-го столбца, заменить.
  • min[$1]=(min[$1]>$2?$2:min[$1]) то же самое с минимумом.
  • END { for (i in max) print i, min[i], max[i]} просмотрите результаты и распечатайте их.

Тестовое задание

$ awk '!($1 in min) {min[$1]=$2; max[$1]=$2} {max[$1]=(max[$1]<$2?$2:max[$1]); min[$1]=(min[$1]>$2?$2:min[$1])} END { for (i in max) print i, min[i], max[i]}' a
yyy 1 10
xxx 0 10

Нам нужно определить минимум и максимум при чтении первой строки!

$ cat a
x -1
x 0
y 1
x -3
$ awk '!($1 in min) {min[$1]=$2; max[$1]=$2} {max[$1]=(max[$1]<$2?$2:max[$1]); min[$1]=(min[$1]>$2?$2:min[$1])} END { for (i in max) print i, min[i], max[i]}' a
x -3 0
y 1 1
person fedorqui 'SO stop harming'    schedule 07.10.2014
comment
Также можно использовать getline, если память ограничена. - person ; 07.10.2014
comment
Я не думаю, что здесь необходимо использовать getline, @Jidder, как бы вы это реализовали? С массивами должно быть достаточно. Об этом есть хорошая статья Эда Мортона, сейчас не могу найти. - person fedorqui 'SO stop harming'; 07.10.2014
comment
Обратите внимание, что я обновил свой первый ответ, он был немного неправильным. - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Читая это снова, нет, я так не думаю. Однако, чтобы реализовать это, для каждого нового 1 доллара он читал файл и находил минимальное и максимальное значение для этого 1 доллара и сохранял их во временной переменной в функции, а затем печатал, а затем мог пропустить весь этот 1 доллар. Однако для этого вопроса это излишне сложно, и я даже не знаю, почему я это предложил. - person ; 07.10.2014
comment
Нет проблем, @Jidder! Всегда полезно переосмыслить то, что мы делаем и как мы это делаем. Спасибо за комментарий :) - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Я пробую первый ваш пост, и он работает очень хорошо. Второй у меня какой-то странный вывод. Оригинал был: awk '{max[$4]=(max[$4]‹$8?$8:max[$4]); min[$4]=(!(min[$4]) || min[$4]›$8?$8:min[$4])}END {for (i in max) выведите i \t min[i] \t max[ я]}' входной_файл - person Paul; 07.10.2014
comment
@Incorigible да, правда, первый код был неправильным. Вот почему я обновился. Спасибо, что дал мне знать. - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Нет, я думаю, что первый код был правильным. Новый дает мне странный результат :-( Я просто проверяю его.. - person Paul; 07.10.2014
comment
@Incorigible странно ... второй у меня отлично работает для каждого образца ввода, который я использую. Кстати, вы всегда можете увидеть предыдущие версии в stackoverflow.com/posts/26236749/revisions. - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui, если 0 является максимальным числом, то max потерпит неудачу по той же причине, что и min. - person ; 07.10.2014
comment
@ Джиддер нет. !(var) верно только в том случае, если var не определено или это 0. Тестировать можно так: записать от -10 до 10 в файл: seq -10 10 >a. Проверить, когда условие выполнено: awk '!$1 {print "it is empty or 0:", $1}' a - person fedorqui 'SO stop harming'; 07.10.2014
comment
Я прочитал это неправильно (опять же! извините), но проблема, с которой я столкнулся, была вызвана тем, что ноль был самым высоким числом, как указано в следующем комментарии. Хотя спасибо за быстрый ответ :) - person ; 07.10.2014
comment
@Jidder извините, я имел в виду ваш предыдущий комментарий. Насчет нуля вы правы. Я только что обновил, определив значения при первом чтении. Спасибо! - person fedorqui 'SO stop harming'; 07.10.2014
comment
@fedorqui Да, я сожалею о своей вине.. Первый код не удался, если мое значение равно нулю.. Новый обновленный код отлично работает со значением 0 (ноль — мое самое низкое значение в моих файлах).. Большое спасибо за ваше время и помощь! Я узнал кое-что новое! - person Paul; 07.10.2014