Добрый день! Коллега jerkyboy выставил на форуме тему: как из массива данных вывести интервалы https://php.ru/forum/threads/kak-iz-massiva-dannyx-vyvesti-intervaly.103045/ PHP PHP: <? function getIntervals($inData){ foreach($inData as $item){ preg_match("/^(\D+)(\d+)$/", $item, $out); $groups[$out[1]][] = $out[2]; } $intervals = []; foreach($groups as $preff => $group){ sort($group); //--------------------------------- $interval = ""; $numberBefor = 0; foreach($group as $number) { $val = $preff.$number; if($numberBefor == 0) $interval = $val; else { if(($number - $numberBefor) > 1) { $valBefor = $preff.$numberBefor; if($interval != $valBefor) $interval .= " - $valBefor"; $intervals[] = $interval; $interval = $val; } } $numberBefor = $number; } if($interval != $val) $interval .= " - $val"; $intervals[] = $interval; } return $intervals; } ################################################################################## echo "<pre>"; $data = ["А8","А7", "А3","А1", "А4","А5", "В23", "В24", "В25", "В26", "Ж32", "Ж33", "Ж34", "Z_1", "Z_2", "Z_3","W 202", "W 203", "W 204"]; $intervals = getIntervals($data); $out = "Intervals:<br>"; foreach($intervals as $interval) $out .= "$interval<br>"; echo $out; /* Intervals: А1 А3 - А5 А7 - А8 В23 - В26 Ж32 - Ж34 Z_1 - Z_3 W 202 - W 204 */ Python Код (Text): import re data = ["А8","А7", "А3","А1", "А4","А5", "В23", "В24", "В25", "В26", "Ж32", "Ж33", "Ж34", "Z_1", "Z_2", "Z_3","W 202", "W 203", "W 204"]; def getintervals(inData): groups = {} patt = re.compile(r'^(\D+)(\d+)$') for item in inData: out = patt.findall(item) key = out[0][0] val = int(out[0][1]) if key in groups: groups[key].append(val) else: groups[key]=[val] intervals = [] for preff in groups: group = groups[preff] group.sort() numberBefor = 0; for number in group: val = preff + str(number) if(numberBefor == 0): interval = val else: if((number - numberBefor) > 1): valBefor = preff + str(numberBefor) if(interval != valBefor): interval += " - " + valBefor intervals.append(interval) interval = val numberBefor = number if(interval != val): interval += " - " + val; intervals.append(interval) return intervals; intervals = getintervals(data); out = "Intervals:\n"; for interval in intervals: out += interval + "\n"; print(out); """ Intervals: А1 А3 - А5 А7 - А8 В23 - В26 Ж32 - Ж34 Z_1 - Z_3 W 202 - W 204 """ C++ Код (Text): #include <iostream> #include <string> #include <regex> #include <map> using namespace std; vector<string> getIntervals(vector<string> inData) { map< string, vector<int> > groups; string interval; string valBefor; string val; vector <int> group; vector <string> intervals; for (auto item : inData) { string str(item); regex r("^(\\D+)(\\d+)$"); smatch m; regex_search(str, m, r); groups[m[1]].push_back(stoi(m[2])); } for (const auto& pair : groups) { string preff = pair.first; group = pair.second; sort(group.begin(), group.end()); int numberBefor = 0; for (int number : group) { val = preff + to_string(number); if (numberBefor == 0) interval = val; else { if ((number - numberBefor) > 1) { valBefor = preff + to_string(numberBefor); if (interval != valBefor) interval += " - " + valBefor; intervals.push_back(interval); interval = val; } } numberBefor = number; } if (interval != val) interval += " - " + val; intervals.push_back(interval); } return intervals; } int main() { vector<string> data{ "А8","А7", "А3","А1", "А4","А5", "В23", "В24", "В25", "В26", "Ж32", "Ж33", "Ж34", "Z_1", "Z_2", "Z_3","W 202", "W 203", "W 204" }; vector<string> intervals = getIntervals(data); cout << "Intervals:" << endl; for (auto interval : intervals) cout << interval << endl; /* Intervals: W 202 - W 204 Z_1 - Z_3 А1 А3 - А5 А7 - А8 В23 - В26 Ж32 - Ж34 */ return 0; } Java Код (Text): import java.util.*; import java.util.regex.*; import java.util.function.Function; public class Main { public static void main(String[] args) { //------------------------------------------------------------------------------ Function < String[], List<String> > getIntervals = ( String[] inData ) -> { Map< String, Vector<Integer> > groups = new HashMap<>(); List<String> intervals = new ArrayList<String>(); Pattern p = Pattern.compile("^(\\D+)(\\d+)$"); for(String item : inData) { Matcher m = p.matcher(item); boolean b = m.matches(); String preff = m.group(1); int number = Integer.parseInt(m.group(2)); if(groups.get(preff) == null) groups.put(preff, new Vector<Integer>()); groups.get(preff).add(number); } groups.entrySet().forEach(entry -> { String preff = entry.getKey(); Vector<Integer> group = new Vector<Integer>(); group = entry.getValue(); Collections.sort(group); int numberBefor = 0; String interval = ""; String val = ""; for(int number : group) { val = preff + Integer.toString(number); if (numberBefor == 0) interval = val; else { if ((number - numberBefor) > 1) { String valBefor = preff + Integer.toString(numberBefor); if (!interval.equals(valBefor)) interval += " - " + valBefor; intervals.add(interval); interval = val; } } numberBefor = number; } if (interval != val) interval += " - " + val; intervals.add(interval); }); return intervals; }; //------------------------------------------------------------------------------ String[] data = { "А8","А7", "А3","А1", "А4","А5", "В23", "В24", "В25", "В26", "Ж32", "Ж33", "Ж34","Z_1", "Z_2", "Z_3","W 202", "W 203", "W 204" }; List<String> intervals = getIntervals.apply(data); String out = "Intervals:\n"; for(String item : intervals) out += item + "\n"; System.out.println(out); /* Output: Intervals: А1 А3 - А5 А7 - А8 В23 - В26 Z_1 - Z_3 Ж32 - Ж34 W 202 - W 204 */ } } ECMAScript Код (Javascript): const data = ["А8","А7", "А3","А1", "А4","А5", "В23", "В24", "В25", "В26", "Ж32", "Ж33", "Ж34", "Z_1", "Z_2", "Z_3","W 202", "W 203", "W 204"]; function getIntervals(inData){ const regex = /^(\D+)(\d+)$/; let groups = {}; for(let item of inData){ let out = regex.exec(item); if(!groups[out[1]]) groups[out[1]]=[]; groups[out[1]].push(out[2]); } let intervals = []; for( let preff in groups) { let group = groups[preff]; group.sort(); let numberBefor = 0; for (let number of group) { var val = preff + number; if(numberBefor == 0) var interval = val; else { beforVal = preff + numberBefor; if((number - numberBefor) > 1) { if(interval != beforVal) interval += ` - ${beforVal}`; intervals.push(interval); interval = val; } } numberBefor = number; } if(interval != val) interval += ` - ${val}`; intervals.push(interval); } return intervals; } const intervals = getIntervals(data); let out = "Intervals:\n"; for(let interval of intervals ) out += `${interval}\n`; alert(out); /* А1 А3 - А5 А7 - А8 В23 - В26 Ж32 - Ж34 Z_1 - Z_3 W 202 - W 204 */ Удачи!
Владимир, Вы молодец, давно Вас чту!) Спасибо за помощь новичкам и просто халявщикам))) Но почему короткие теги используем? Это рано или поздно а) удалят б) тыЩщщу лет как не рекомендуют использовать в) Могут возникать различные конфликты, например с xml г) не везде "прокатит" (т.е. не будет работать), просто потому, что они там отключены. Не всегда есть возможность включить при желании или наоборот. Времена другие, правила поменялись, меняйтесь и Вы! В ногу, да со временем!) Эх, где мой любимый 5.3
Добрый день! Спасибо за Ваш комментарий. Относительно коротких тэгов, Вы правы, возможно их когда-нибудь их запретят использовать и из конфига уберут настройку. На всякий случай в PHP-коде заменил короткий тэг на длинный. Онако, это не гланое. Не заю как вам, но не нравится то, что рассмореная задача абстракная и не имеет практического смысла. Теперь, хотел бы рассмотреть практическую задачу про интевалы дат: Допустим, что заданы два неупорядоченных набора дат: 1. Набор из пар полных названий месяцов и дат: Код (Text): "January 8", "May 11", "January 3","January 1", "April 2", "January 4","January 5", "May 11","February 24", "April 1", "February 25", "February 26", "March 12", "January 7", "March 13", "January 3", "March 14", "February 24", "April 3","May 10", "May 12","February 23" 2. Набор ISO-дат: Код (Text): "2025-05-10", "2025-03-14","2025-05-11", "2025-01-04", "2025-03-13", "2025-01-08","2025-05-12", "2025-01-03", "2025-04-03","2025-02-24", "2025-01-01", "2025-01-05", "2025-02-23", "2025-02-25", "2025-02-26", "2025-03-12", "2025-04-01", "2025-04-02", "2025-01-07" Требуется вычислить для этих данных упорядоченные интевалы дат по месяцам, например: Код (Text): intervals: Days in January 1 3 - 5 7 - 8 Days in February 23 - 26 Days in March 12 - 14 Days in April 1 - 3 Days in May 10 - 12 PHP: PHP: <?php function getIntervals($inData){ $months = getMonths(); foreach((array)$inData as $item){ $pattern1 = "/^(\D+)(\d+)$/"; $pattern2 = "/^(\d{4})\-(\d{2})\-(\d{2})$/"; if(preg_match($pattern1, $item, $out)) { $month = array_search(trim($out[1]), $months); $day = intval($out[2]); } else if(preg_match($pattern2, $item, $out2)) { $month = intval($out2[2])-1; $day = intval($out2[3]); } else return false; $groups[$month][] = $day; } ksort($groups); foreach($groups as $preff => $group){ sort($group); //--------------------------------- $interval = ""; $numberBefor = 0; foreach($group as $number) { if($numberBefor == 0) $interval = $number; else { if(($number - $numberBefor) > 1) { if($interval != $numberBefor) $interval .= " - $numberBefor"; $intervals[$preff][] = $interval; $interval = $number; } } $numberBefor = $number; } if($interval != $number) $interval .= " - $number"; $intervals[$preff][] = $interval; } return $intervals; } //--------------------------------------------------------- function viewIntervals($intervals){ if($intervals) { $months = getMonths(); $out = "-----------------------------------<br>"; $out .= "Intervals:<br>"; foreach($intervals as $month => $interval){ $out .= "Days in {$months[$month]}:<br>"; foreach($interval as $numberDays) { $out .= "$numberDays<br>"; } $out .= "<br>"; } echo $out; } } //--------------------------------------------------------- function getMonths(){ return array_map(fn (int $m): string => (DateTime::createFromFormat('m-d', "$m-1") -> format('F')), range(1, 12),); } //--------------------------------------------------------- $data = ["January 8", "May 11", "January 3","January 1", "April 2", "January 4","January 5", "May 11","February 24", "April 1", "February 25", "February 26", "March 12", "January 7", "March 13", "January 3", "March 14", "February 24", "April 3","May 10", "May 12","February 23"]; $intervals = getIntervals($data); viewIntervals($intervals); //------------------------------------------------------- $data = ["2025-05-10", "2025-03-14","2025-05-11", "2025-01-04", "2025-03-13", "2025-01-08","2025-05-12", "2025-01-03", "2025-04-03","2025-02-24", "2025-01-01", "2025-01-05", "2025-02-23", "2025-02-25", "2025-02-26", "2025-03-12", "2025-04-01", "2025-04-02", "2025-01-07"]; $intervals = getIntervals($data); viewIntervals($intervals); /* ----------------------------------- Intervals: Days in January: 1 3 - 5 7 - 8 Days in February: 23 - 26 Days in March: 12 - 14 Days in April: 1 - 3 Days in May: 10 - 12 ----------------------------------- Intervals: Days in January: 01 03 - 05 07 - 08 Days in February: 23 - 26 Days in March: 12 - 14 Days in April: 01 - 03 Days in May: 10 - 12 */ Python: Код (Text): import re import datetime import calendar def getintervals(inData): groups = {} patt1 = re.compile(r'^(\D+)(\d+)$') patt2 = re.compile(r'^(\d{4})\-(\d{2})\-(\d{2})$') intervals = {} for item in inData: if re.match(patt1,item): out = patt1.findall(item) month = list(calendar.month_name).index(out[0][0].strip()); day = int(out[0][1]) elif re.match(patt2,item): out = patt2.findall(item) month = int(out[0][1]) day = int(out[0][2]) else: return intervals if month in groups: groups[month].append(day) else: groups[month]=[day] monthGroups = sorted(list(groups.keys())) for preff in monthGroups: group = groups[preff] group.sort() numberBefor = 0 for number in group: val = str(number) if numberBefor == 0: interval = val else: if number - numberBefor > 1: valBefor = str(numberBefor) if interval != valBefor: interval += " - " + valBefor if preff in intervals: intervals[preff].append(interval) else: intervals[preff]=[interval] interval = val numberBefor = number if interval != val: interval += " - " + val; if preff in intervals: intervals[preff].append(interval) else: intervals[preff] = [interval] return intervals; #-------------------------------------- def viewIntervals(intervals): out = "---------------------\n\n" out += "intervals:\n\n" for month in intervals: out += "Days in " + calendar.month_name[month] + "\n" for numberDays in intervals[month]: out += numberDays + "\n" out += "\n" print(out) #-------------------------------------- data = ["January 8", "May 11", "January 3","January 1", "April 2", "January 4","January 5", "May 11","February 24", "April 1", "February 25", "February 26", "March 12", "January 7", "March 13", "January 3", "March 14", "February 24", "April 3","May 10", "May 12","February 23"]; intervals = getintervals(data) viewIntervals(intervals) #------------------------------------------------------------ data = ["2025-05-10", "2025-03-14","2025-05-11", "2025-01-04", "2025-03-13", "2025-01-08","2025-05-12", "2025-01-03", "2025-04-03","2025-02-24", "2025-01-01", "2025-01-05", "2025-02-23", "2025-02-25", "2025-02-26", "2025-03-12", "2025-04-01", "2025-04-02", "2025-01-07"]; intervals = getintervals(data) viewIntervals(intervals) """ Output: --------------------- intervals: Days in January 1 3 - 5 7 - 8 Days in February 23 - 26 Days in March 12 - 14 Days in April 1 - 3 Days in May 10 - 12 --------------------- intervals: Days in January 1 3 - 5 7 - 8 Days in February 23 - 26 Days in March 12 - 14 Days in April 1 - 3 Days in May 10 - 12 """ C++, Java и ECMAScript в zip-файле Удачи!