$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>categories - Alphabetical Index Page|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

categories - Alphabetical Index Page

matteradmin11PV0评论

I can't quite seem to wrap my head around the logic needed to create an Alphabetical Index page. I can get a rudimentary version working but what I'm trying to do is create something like this /.

So far I have my code outputting the first letter of a set of taxonomy terms and then every time it finds a new letter it adds the letter to the index.

What I cannot figure out is A) How to equally divide the posts into columns (Bootstrap markup being wrapped in <div class="col-sm-2"> and B) If I can get that working then how to group 3 letters together at a time ie) A-C, D-F, etc.

Here is my code so far:

<?php
$args = array(
    'taxonomy' => 'brands',
    'hide_empty' => 0,
    'orderby' => 'name',
    'order' => 'ASC',
);
$category_list = get_categories($args);
$curr_letter = '';

foreach ( $category_list as $category ) {
    $this_letter = strtoupper(substr($category->name,0,1));

    if ($this_letter != $curr_letter) {
        echo !empty( $curr_letter ) ? '</div>' : null;
        echo '<div class="row">';
        echo '<h3 class="col-sm-2">' . $this_letter . '</h3>';
        $curr_letter = $this_letter;
    }
    echo '<div class="col-sm-2">' . $category->name . '</div>';
}
?>

I thought of trying to store every nth iteration of the loop into a new array for each of the columns and then emptying the arrays when it hits a new letter but I'm not entirely sure how to do that. Perhaps someone can point me in the right direction.

I can't quite seem to wrap my head around the logic needed to create an Alphabetical Index page. I can get a rudimentary version working but what I'm trying to do is create something like this https://www.carryology/brands/.

So far I have my code outputting the first letter of a set of taxonomy terms and then every time it finds a new letter it adds the letter to the index.

What I cannot figure out is A) How to equally divide the posts into columns (Bootstrap markup being wrapped in <div class="col-sm-2"> and B) If I can get that working then how to group 3 letters together at a time ie) A-C, D-F, etc.

Here is my code so far:

<?php
$args = array(
    'taxonomy' => 'brands',
    'hide_empty' => 0,
    'orderby' => 'name',
    'order' => 'ASC',
);
$category_list = get_categories($args);
$curr_letter = '';

foreach ( $category_list as $category ) {
    $this_letter = strtoupper(substr($category->name,0,1));

    if ($this_letter != $curr_letter) {
        echo !empty( $curr_letter ) ? '</div>' : null;
        echo '<div class="row">';
        echo '<h3 class="col-sm-2">' . $this_letter . '</h3>';
        $curr_letter = $this_letter;
    }
    echo '<div class="col-sm-2">' . $category->name . '</div>';
}
?>

I thought of trying to store every nth iteration of the loop into a new array for each of the columns and then emptying the arrays when it hits a new letter but I'm not entirely sure how to do that. Perhaps someone can point me in the right direction.

Share Improve this question asked Mar 5, 2019 at 3:38 tylorreimertylorreimer 651 silver badge8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 5

You can do it like so:

// Group the categories by their FIRST LETTER.
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

// Now display them, three groups in each row.
echo '<div class="row">';
$i = 0;
$letters = array_keys( $groups );
foreach ( $groups as $letter => $terms ) {
    $new_row = ( $i % 3 === 0 );
    if ( $i && $new_row ) {
        echo '</div><div class="row">';
    }

    // Show either "A - C", "A & B", or just a letter.
    if ( ! $i || $new_row ) {
        $range = array_slice( $letters, $i, 3 );
        if ( $end = $range[ count( $range ) - 1 ] ) {
            $sign = ( count( $range ) > 2 ) ? ' - ' : ' & ';
            $range = $letter . $sign . $end;
            echo '<h2 class="col-12">' . $range . '</h2>';
        } else {
            echo '<h2 class="col-12">' . $letter . '</h2>';
        }
    }

    echo '<div class="col-sm">';
    if ( ! empty( $terms ) ) {
        echo '<ul>';
        foreach ( $terms as $term ) {
            echo '<li>' . $term->name . '</li>';
        }
        echo '</ul>';
    }
    echo '</div>';

    $i++;
}
echo '</div>';

The output would look like so:


UPDATE

So this is the proper version, based on the layout on Carryology/brands/ (as of writing).

I have commented the code (although not all parts) and it shouldn't be hard for you to make modifications to the code:

// Group the categories by their FIRST LETTER.
$letters = range( 'A', 'Z' );
$groups = [];
foreach ( $category_list as &$term ) {
    $letter = strtoupper( substr( $term->name, 0, 1 ) );
    if ( ! isset( $groups[ $letter ] ) ) {
        $groups[ $letter ] = [];
    }

    $groups[ $letter ][] = $term;
}

$cols = 3; // number of letters in a range
for ( $i = 0; $i < count( $letters ); $i++ ) {
    if ( $i % $cols === 0 ) {
        $list = array_slice( $letters, $i, $cols );
        // Start the row.
        echo '<div class="row">';

        // Show the heading. (letter range)
        $end = $list[ count( $list ) - 1 ];
        $sign = ( count( $list ) > 2 ) ? ' - ' : ' & ';
        $range = $end ? $sign . $end : '';
        // Show either "A - C", "A & B", or just a letter.
        echo '<h3 class="col-sm-2">' . $list[0] . $range . '</h3>';

        // Put all the letter terms in a single group.
        $groups2 = [];
        for ( $j = 0; $j < count( $list ); $j++ ) {
            if ( isset( $groups[ $list[ $j ] ] ) ) {
                $groups2 = array_merge( $groups2, $groups[ $list[ $j ] ] );
            }
        }

        $cols2 = 5; // number of columns in a row, excluding the heading.
        $n = count( $groups2 );
        $rows = floor( $n / $cols2 );
        $diff = $n - $rows * $cols2;
        for ( $k = 0, $l = 0; $k < $cols2; $k++ ) {
            $x = $diff ? 1 : 0;
            // Start a column.
            echo '<ul class="col-xs-4 col-sm-2">';

            // Show the group terms.
            foreach ( array_slice( $groups2, $l, $rows + $x ) as $term ) {
                echo '<li>' . $term->name . '</li>';
                $l++;
            }

            $diff = $diff ? $diff - 1 : 0;
            // Column end.
            echo '</ul>';
        }

        // Row end.
        echo '</div>';
    }
}

The output would look like so:

Articles related to this article

Post a comment

comment list (0)

  1. No comments so far