根据共享时间范围将二维数组数据格式化为连字符连续日期范围的字符串

发布于 2024-12-10 03:15:33 字数 857 浏览 0 评论 0原文

我从 API 获得的数据的格式相当难以使​​用(以必需使用的方式)——我没有能力修改 API。下面是我得到的数据的示例:

$data = array(
    array('day' => 'Monday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Tuesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Wednesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Thursday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Friday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Saturday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Sunday', 'start' => 1200, 'end' => 1400)
);

数据可能不包括一周中的所有 7 天,开始和结束在 0000 到 2400 之间变化。我试图想出一种使用以下输出格式化数据的方法:

Monday - Wednesday (1100-1300), Thursday - Saturday (1200-1300), Sunday (1200-1400)

基本上,连续的日期(其开始时间和结束时间相同)由连字符分隔。

我有点试图避免一大堆丑陋的代码。

I am given data from an API in a format that is pretty difficult to use (in the manner that is necessary to be used in) - I do not have the ability to modify the API. Below is an example of the data I am given:

$data = array(
    array('day' => 'Monday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Tuesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Wednesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Thursday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Friday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Saturday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Sunday', 'start' => 1200, 'end' => 1400)
);

The data may not include all seven days of the week, start and end vary between 0000 and 2400. I am trying to come up with a way to format the data with the following output:

Monday - Wednesday (1100-1300), Thursday - Saturday (1200-1300), Sunday (1200-1400)

Basically, contiguous days (whose start and end times are the same) are separated by a hyphen.

I am kind of trying to avoid a huge block of ugly code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

本宫微胖 2024-12-17 03:15:33

丑陋是情人眼里出西施。 ;)我认为这没关系,但当然这可能正是您想要避免的。

<?php
$data = array(
    array('day' => 'Monday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Tuesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Wednesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Thursday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Friday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Saturday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Sunday', 'start' => 1200, 'end' => 1400)
);

$periods = array();

$start = $end = $i = -1;

foreach ($data as $datum) {
    if ($start != $datum['start'] || $end != $datum['end']) {
        $i++;
        $start = $datum['start'];
        $end   = $datum['end'];

        $periods[$i] = array(
                          'start'    => $start, 
                          'end'      => $end,
                          'startDay' => $datum['day']);
    }
    $periods[$i]['endDay'] = $datum['day'];
}

foreach ($periods as $k => $period) {
    echo ($k) ? ', ' : '';
    if ($period['startDay'] === $period['endDay']) {
        echo $period['startDay'];
    } else {
        echo "{$period['startDay']} - {$period['endDay']}";
    }
    echo " ({$period['start']} - {$period['end']})";
}

会输出:

Monday - Wednesday (1100 - 1300), Thursday - Saturday (1200 - 1300), Sunday (1200 - 1400)

Ugliness is in the eye of the beholder. ;) I think this is OK, but of course it might be exactly what you're trying to avoid.

<?php
$data = array(
    array('day' => 'Monday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Tuesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Wednesday', 'start' => 1100, 'end' => 1300),
    array('day' => 'Thursday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Friday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Saturday', 'start' => 1200, 'end' => 1300),
    array('day' => 'Sunday', 'start' => 1200, 'end' => 1400)
);

$periods = array();

$start = $end = $i = -1;

foreach ($data as $datum) {
    if ($start != $datum['start'] || $end != $datum['end']) {
        $i++;
        $start = $datum['start'];
        $end   = $datum['end'];

        $periods[$i] = array(
                          'start'    => $start, 
                          'end'      => $end,
                          'startDay' => $datum['day']);
    }
    $periods[$i]['endDay'] = $datum['day'];
}

foreach ($periods as $k => $period) {
    echo ($k) ? ', ' : '';
    if ($period['startDay'] === $period['endDay']) {
        echo $period['startDay'];
    } else {
        echo "{$period['startDay']} - {$period['endDay']}";
    }
    echo " ({$period['start']} - {$period['end']})";
}

Would output:

Monday - Wednesday (1100 - 1300), Thursday - Saturday (1200 - 1300), Sunday (1200 - 1400)
往事随风而去 2024-12-17 03:15:33

在循环遍历行时,无条件地尝试写入或覆盖与当前星期几相同的小时范围(如果位于字符串)之前的单词。如果替换尝试失败,请将当前日期和时间范围附加到字符串末尾。

该脚本的优点是不需要预先对数据进行分组,然后再次循环以呈现分组的数据。这种方法只是一个注入或串联过程。 Demo

$data = [
    ['day' => 'Monday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Tuesday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Wednesday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Thursday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Friday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Saturday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Sunday', 'start' => 1200, 'end' => 1400],
];

function hyphenateConsecutiveDaysWithDuplicateTimes(array $rows): string {
    $string = '';
    foreach ($rows as $row) {
        $time = "({$row['start']}-{$row['end']})";
        $string = preg_replace(
            "/(?: - [^(]+)?(?= \Q$time\E$)/",
            " - {$row['day']}",
            $string,
            1,
            $count
        );
        if (!$count) {
            $string .= ($string ? ', ' : '') . "{$row['day']} $time";
        }
    }
    return $string;
}

echo hyphenateConsecutiveDaysWithDuplicateTimes($data);

正则表达式模式:

(?:        #start of non-capturing group
    -      #match space, hyphen, space
   [^(]+   #match one or more non-opening-parentheses
)?         #end of non-capture group and allow zero or one of the internal match
(?=        #start of lookahead      
    \Q     #match space, then tell the engine to treat everything literally
   $time   #match the parenthetical time range expression
   \E      #tell the engine to stop treating everything literally
   $       #match the end of the string
)          #end the lookahead

如果上面的脚本不够漂亮或不够直观,也许可以声明更多变量来实现它更具表现力。

function hyphenateConsecutiveDaysWithDuplicateTimes(array $rows): string {
    $string = '';
    $optionalEndDay = '(?: - [^(]+)?';
    foreach ($rows as $row) {
        extract($row);
        $time = "($start-$end)";
        $sameTimeRange = "(?= \Q$time\E$)";
        $string = preg_replace("/$optionalEndDay$sameTimeRange/", " - $day", $string, 1, $count);
        if (!$count) {
            $string .= ($string ? ', ' : '') . "$day $time";
        }
    }
    return $string;
}

While looping over the rows unconditionally attempt to write or overwrite the word before the identical hour range (if at the string) with the current day of the week. If that replacement attempt fails, append the current day and time range to the end of the string.

This script has the benefit of not needing to pre-group the data and then loop again to present the grouped data. This approach is only an injection or concatenation process. Demo

$data = [
    ['day' => 'Monday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Tuesday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Wednesday', 'start' => 1100, 'end' => 1300],
    ['day' => 'Thursday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Friday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Saturday', 'start' => 1200, 'end' => 1300],
    ['day' => 'Sunday', 'start' => 1200, 'end' => 1400],
];

function hyphenateConsecutiveDaysWithDuplicateTimes(array $rows): string {
    $string = '';
    foreach ($rows as $row) {
        $time = "({$row['start']}-{$row['end']})";
        $string = preg_replace(
            "/(?: - [^(]+)?(?= \Q$time\E$)/",
            " - {$row['day']}",
            $string,
            1,
            $count
        );
        if (!$count) {
            $string .= ($string ? ', ' : '') . "{$row['day']} $time";
        }
    }
    return $string;
}

echo hyphenateConsecutiveDaysWithDuplicateTimes($data);

The regex pattern:

(?:        #start of non-capturing group
    -      #match space, hyphen, space
   [^(]+   #match one or more non-opening-parentheses
)?         #end of non-capture group and allow zero or one of the internal match
(?=        #start of lookahead      
    \Q     #match space, then tell the engine to treat everything literally
   $time   #match the parenthetical time range expression
   \E      #tell the engine to stop treating everything literally
   $       #match the end of the string
)          #end the lookahead

If the above script isn't pretty or intuitive enough, maybe declare more variables to make it more expressive.

function hyphenateConsecutiveDaysWithDuplicateTimes(array $rows): string {
    $string = '';
    $optionalEndDay = '(?: - [^(]+)?';
    foreach ($rows as $row) {
        extract($row);
        $time = "($start-$end)";
        $sameTimeRange = "(?= \Q$time\E$)";
        $string = preg_replace("/$optionalEndDay$sameTimeRange/", " - $day", $string, 1, $count);
        if (!$count) {
            $string .= ($string ? ', ' : '') . "$day $time";
        }
    }
    return $string;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文