使用 PHP 填充均匀分布的数组矩阵

发布于 2024-09-27 20:16:47 字数 1957 浏览 4 评论 0原文

我有一个对象数组,其中包含时间列表。我必须将其放入类似矩阵的数组中,以便将其放入表格中。这是我的之前关于如何构建日历表的问题

$node->sessions = array(
  1286452800, // '2010-10-07 14:00:00'
  1286460000, // '2010-10-07 16:00:00'
);
$node->title = 'Foo';
$nodes[1] = $node;

$node->sessions = array(
  1286452800, // '2010-10-07 14:00:00'
  1286460000, // '2010-10-07 16:00:00'
  1286461800, // '2010-10-07 16:30:00'
);
$node->title = 'Bar';
$nodes[2] = $node;

$node->sessions = array(
  1286460000, // '2010-10-07 16:00:00'
  1286461800, // '2010-10-07 16:30:00'
  1286465400, // '2010-10-07 17:30:00'
);
$node->title = 'Baz';
$nodes[3] = $node;

这些代表电影播放日期的表。正如此处的实际操作所示。目前的代码过于复杂(恕我直言),可以简化,只是我不知道如何简化。也许通过一些矩阵库?或者我不知道的一些算法?

生成的结构应该是一个表示标题(表的列名)的数组和一个表示行的数组。如下:

$header = array(
  ' ', // empty "cell"
  ttt, // ttt being the timestamp for '14:00'
  uuu, // idem for '15:00'
  vvv, // idem for '16:00'
  www, // idem '17:00'
);
//  title, 14:00, 15:00, 16:00, 17:00
$rows = array(
  array(
    'Bar', 1286452800,  '', array(1286460000, 1286461800), '',  //Both 16:00 and 16:30 grouped under 16:00 'header'
  ),
  array(
    'Baz', '',  '', array(1286460000, 1286461800), 1286465400
  ),
  array(
    'Foo', 1286452800,  '', 1286460000,  '',
  )  
);

每行应具有相同数量的“单元格”。 时间戳应按其所属时间分组(16:15、16:30 等均分组在 16:00 下) 另请注意,上面给出的输出结构也可能会被优化,请告诉我是否有办法通过简化或更改生成的“矩阵”来简化代码。

我现在所做的伪代码:

  1. 对所有$nodes 按标题
  2. 循环排序 $nodes 以查找矩阵的宽度(14:00 到 17:00),并
  3. 在所有 $nodes 上填充 $header 循环再次 $nodes,对于每个节点,循环遍历 $header 并用空 ('') 或时间戳填充数组。

现在,对于上面的三个条目,这不是一个大问题,但是这个矩阵可能会变得非常宽(大 $headers 数组)和深(许多 $nodes),从而导致大量重复循环。 但性能和重复循环并不是我最关心的,主要是拥有更干净、更少嵌套、更简单的代码。 :)

I have an array of objects, containing lists of times. I have to stick this in a Matrix-alike array, in order to put it in a table. This is a part of my earlier SO question on how to build calendar tables

$node->sessions = array(
  1286452800, // '2010-10-07 14:00:00'
  1286460000, // '2010-10-07 16:00:00'
);
$node->title = 'Foo';
$nodes[1] = $node;

$node->sessions = array(
  1286452800, // '2010-10-07 14:00:00'
  1286460000, // '2010-10-07 16:00:00'
  1286461800, // '2010-10-07 16:30:00'
);
$node->title = 'Bar';
$nodes[2] = $node;

$node->sessions = array(
  1286460000, // '2010-10-07 16:00:00'
  1286461800, // '2010-10-07 16:30:00'
  1286465400, // '2010-10-07 17:30:00'
);
$node->title = 'Baz';
$nodes[3] = $node;

These represent a table of playdates of movies. As can be seen in action here. The code for this, right now is far too complex (IMHO) and could be simplified, just that I don't know how. Maybe trough some Matrix-library? Or some algorythm that I am unaware of?

The resulting structure, should be an array representing the header (column names of the table) and an array-with-arrays representing the rows. As follows:

$header = array(
  ' ', // empty "cell"
  ttt, // ttt being the timestamp for '14:00'
  uuu, // idem for '15:00'
  vvv, // idem for '16:00'
  www, // idem '17:00'
);
//  title, 14:00, 15:00, 16:00, 17:00
$rows = array(
  array(
    'Bar', 1286452800,  '', array(1286460000, 1286461800), '',  //Both 16:00 and 16:30 grouped under 16:00 'header'
  ),
  array(
    'Baz', '',  '', array(1286460000, 1286461800), 1286465400
  ),
  array(
    'Foo', 1286452800,  '', 1286460000,  '',
  )  
);

Each row should have the same amount of "cells".
Timestamps should be grouped under the hour they belong to (16:15, 16:30 etc all grouped under 16:00)
Also note that the above-given output structure might be optimised too, please let me know if there are ways to simplify the code, by simplifying or changing the resulting "matrix".

Pseudocode for what I do now:

  1. usort $nodes by title
  2. loop over all the $nodes to find the width of the matrix (14:00 to 17:00) and fill the $header
  3. loop over all the $nodes again, for each node loop over $header and fill an array with either empties ('') or with the timestamps.

Now, for a the three entries above, that is not a big problem, but this matrix can grow very wide (large $headers array) and deep (many $nodes) resulting in a lot of duplicate looping.
But performance and duplicate looping is not my greatest concern, mostly having cleaner and less nested, less complex code, is. :)

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

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

发布评论

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

评论(1

囚我心虐我身 2024-10-04 20:16:47

我正在放弃你的想法,并想出我会如何做,希望它可以帮助你。

首先以这种格式获取数据:

$movies = array (
    array (
        'title' => 'Babies',
        'times' => array(
                    1286460000,1286467200,1286476200,1286487000
        )
    ),
    array (
        'title' => 'El secreto de sus ojos',
        'times' => array(
                    1286474400,1286481600,1286483400
        )
    )
    // more movies...
);

这是工作代码的链接:http://ideone.com/P4zZn

这里是代码

<?php
date_default_timezone_set('GMT');
$start_hour = 12; // Start hour of matrix
$end_hour = 22; // End hour of matrix
$skip_hours = array( 18, 20 );

// Get the timestamp for each hour in the matrix
foreach( range( $start_hour, $end_hour ) as $hr ) {
    if ( in_array( $hr, $skip_hours ) ) {
        continue;
    }
    $time_sections[] = mktime( $hr,0,0, 10, 7, 2010 ); // You'll want to put null or the month/day to use the current month/day
}

$movies = array (
    array (
        'title' => 'Babies',
        'times' => array(
                    1286460000,1286467200,1286476200,1286487000
        )
    ),
    array (
        'title' => 'El secreto de sus ojos',
        'times' => array(
                    1286474400,1286481600,1286483400
        )
    )
);


?>

<table border="1">
    <thead>
        <th>Movie</th>
        <?php foreach( $time_sections as $time_section ): ?>
        <th><?php echo date( 'G:i', $time_section ) ?> </th>
        <?php endforeach; ?>
    </thead>
    <tbody>
    <?php foreach( $movies as $movie ): ?>
        <tr>
            <td><?php echo $movie['title'] ?></td>
            <?php foreach( $time_sections as $time_section_index => $time_section ): ?>
            <td>
                <!-- while there are movie times left and the first movie time in the array is less than the next timestamp print the movie time -->
                <?php while( count( $movie['times'] ) && current( $movie['times'] ) < $time_sections[$time_section_index + 1] ): ?>
                    <!-- echo the time and pull it from the array -->
                    <?php echo date( 'G:i', array_shift( $movie['times'] ) ) ?> 
                <?php endwhile; ?>
            </td>
            <?php endforeach; ?>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>

I'm scrapping your and coming up with how i would do it in hopes it may help you.

First get the data in this format:

$movies = array (
    array (
        'title' => 'Babies',
        'times' => array(
                    1286460000,1286467200,1286476200,1286487000
        )
    ),
    array (
        'title' => 'El secreto de sus ojos',
        'times' => array(
                    1286474400,1286481600,1286483400
        )
    )
    // more movies...
);

Here's a link to working code: http://ideone.com/P4zZn

Here's the code

<?php
date_default_timezone_set('GMT');
$start_hour = 12; // Start hour of matrix
$end_hour = 22; // End hour of matrix
$skip_hours = array( 18, 20 );

// Get the timestamp for each hour in the matrix
foreach( range( $start_hour, $end_hour ) as $hr ) {
    if ( in_array( $hr, $skip_hours ) ) {
        continue;
    }
    $time_sections[] = mktime( $hr,0,0, 10, 7, 2010 ); // You'll want to put null or the month/day to use the current month/day
}

$movies = array (
    array (
        'title' => 'Babies',
        'times' => array(
                    1286460000,1286467200,1286476200,1286487000
        )
    ),
    array (
        'title' => 'El secreto de sus ojos',
        'times' => array(
                    1286474400,1286481600,1286483400
        )
    )
);


?>

<table border="1">
    <thead>
        <th>Movie</th>
        <?php foreach( $time_sections as $time_section ): ?>
        <th><?php echo date( 'G:i', $time_section ) ?> </th>
        <?php endforeach; ?>
    </thead>
    <tbody>
    <?php foreach( $movies as $movie ): ?>
        <tr>
            <td><?php echo $movie['title'] ?></td>
            <?php foreach( $time_sections as $time_section_index => $time_section ): ?>
            <td>
                <!-- while there are movie times left and the first movie time in the array is less than the next timestamp print the movie time -->
                <?php while( count( $movie['times'] ) && current( $movie['times'] ) < $time_sections[$time_section_index + 1] ): ?>
                    <!-- echo the time and pull it from the array -->
                    <?php echo date( 'G:i', array_shift( $movie['times'] ) ) ?> 
                <?php endwhile; ?>
            </td>
            <?php endforeach; ?>
        </tr>
    <?php endforeach; ?>
    </tbody>
</table>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文