Вопрос или проблема
У меня есть данные в следующем формате, где в первой строке нижние и верхние значения одинаковы, а в следующей строке нижние и верхние значения образуют диапазон (т.е. от 73760 до 73796). Мне нужно подсчитать количество всех строк, где нижние и верхние значения одинаковы, и, с другой стороны, количество всех строк, где нижние и верхние значения образуют диапазон, а также расширенное количество диапазонных данных (т.е. количество значений в диапазоне).
Вывод будет следующим:
индивидуальные данные : 1
диапазонные данные : 1
расширенный диапазон : 37 (расширение от 73760 до 73796)
Входные данные выглядят следующим образом:
TMI=012813 FCI=00 low=000654 up=000654 sor=0E
TMI=012813 FCI=00 low=073760 up=073796 sor=0E
С помощью perl
:
perl -lne '
if (/ low=(\d+) up=(\d+) /) {
$range = $2 - $1 + 1;
$count[$range == 1]++;
$max_range = $range if $range > $max_range;
}
END {
printf "индивидуальные данные: %d\nдиапазонные данные: %d\nрасширенный диапазон: %d\n",
$count[1], $count[0], $max_range;
}' < ваш-файл
Или если расширенный диапазон подразумевает общий диапазон всех значений для недискретных значений, в отличие от максимальной длины диапазона для любой одной строки:
perl -lne '
if (/ low=(\d+) up=(\d+) /) {
$count[$2 == $1]++;
unless ($1 == $2) {
$min_low = $1 if $1 < $min_low;
$max_up = $2 if $2 > $max_up;
}
}
END {
printf "индивидуальные данные: %d\nдиапазонные данные: %d\nрасширенный диапазон: %d\n",
$count[1], $count[0], $max_up - $min_low + 1;
}' < ваш-файл
С помощью Miller (mlr
):
$ mlr --ifs space put -q -f script file
Расширенный диапазон: 37 (73760 до 73796)
Единственные данные: 1
Диапазонные данные: 1
Входные данные выглядят очень похоже на DKVP (“разделенные пары ключ-значение”), родной формат данных Miller, но используют пробелы вместо запятых для разделителей полей, поэтому мы используем --ifs space
в командной строке mlr
для установки разделителя входных полей.
Скрипт в script
был вдохновлен ответом Stéphane, но интерпретирует вопрос так, как будто вы хотите видеть расширенный диапазон для всех диапазонов длиной больше 1.
lo = int($low, 10);
hi = int($up, 10);
range = 1 + hi - lo;
@count[int(range == 1)] += 1;
if (range > 1) {
print "Расширенный диапазон: " . range . " (" . lo . " до " . hi . ")";
}
end {
print "Единственные данные: " . @count[1];
print "Диапазонные данные: " . @count[0];
}
Ответ или решение
Чтобы решить задачу подсчета строк с идентичными и диапазонными значениями, включая расширение диапазона, нужно внимательно рассмотреть данные, которые вы предоставили. Мы будем разбираться с теми строками, в которых значения "low" и "up" меняются, что позволяет нам делить данные на две категории: отдельные значения и диапазоны.
Анализ задачи
Дан набор строк, каждая из которых содержит параметры, включая "low" и "up". Задача состоит в следующем:
- Посчитать количество строк, где значения "low" и "up" одинаковые (индивидуальные данные).
- Посчитать количество строк, где значения "low" и "up" образуют диапазон (диапазонные данные).
- Рассчитать расширенный диапазон для всех диапазонных значений, то есть количество значений в диапазоне.
Примеры данных
Входные данные выглядят следующим образом:
TMI=012813 FCI=00 low=000654 up=000654 sor=0E
TMI=012813 FCI=00 low=073760 up=073796 sor=0E
- Первая строка содержит одинаковые значения (low = up = 654).
- Вторая строка представляет диапазон (от 73760 до 73796).
Ожидаемый вывод
В соответствии с вашими требованиями, вывод должен быть следующим:
individual data: 1
range data: 1
range expanded: 37 (expansion of 73760 to 73796)
Реализация на Perl
Мы можем использовать Perl для подсчета и расширения диапазонов.
perl -lne '
if (/ low=(\d+) up=(\d+) /) {
$low = $1;
$up = $2;
$range = $up - $low + 1;
$count[$range == 1]++;
$max_range = $range if $range > $max_range;
if ($range > 1) {
$expanded_count += $range;
$min_low = $low if !defined $min_low || $low < $min_low;
$max_up = $up if !defined $max_up || $up > $max_up;
}
}
END {
printf "individual data: %d\nrange data: %d\nrange expanded: %d (expansion of %d to %d)\n",
$count[1], $count[0], $max_range, $min_low, $max_up;
}' < your-file
Реализация на Miller (mlr)
Если вы предпочитаете использовать Miller, это возможно тоже:
$ mlr --ifs space put -q -f script file
Где script
будет следующим:
lo = int($low, 10);
hi = int($up, 10);
range = 1 + hi - lo;
@count[int(range == 1)] += 1;
if (range > 1) {
print "Range expanded: " . range . " (" . lo . " to " . hi . ")";
}
end {
print "Single data: " . @count[1];
print "Ranged data: " . @count[0];
}
Заключение
Эти подходы, как на Perl, так и на Miller, предоставляют эффективный способ обработки данных с целью подсчета уникальных и диапазонных значений. Простота и мощь этих утилит позволяет быстро адаптироваться к меняющимся требованиям и объемам данных, что делает их незаменимыми инструментами для IT-специалистов.
Оптимизация SEO
Не забывайте, что такие статьи могут также включать ключевые слова, такие как "подсчет строк", "обработка данных на Perl", "анализ диапазонов", "машинное обучение и данные", что повысит видимость статьи в поисковых системах.