+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: [PHP] Search a multidimensional array

  1. #1
    diabolo's Avatar
    diabolo is offline Community Advocate diabolo is on a distinguished road
    Join Date
    Nov 2007
    Location
    Jersey Shore
    Posts
    1,683

    [PHP] Search a multidimensional array

    PHP Code:
    $textbook = array(
       
    'cantonese' => array(
          
    'class1' => array(
             array(
    '1''One - Two''Chapter 1 to Chapter 2',
                       
    'text'),
             array(
    '3''Three - Five''Chapter 3 to Chapter5',
                       
    'text'),
             array(
    '6''Six - Eight''Chapter 6 to Chapter 8',
                       
    'text'),
          ),
          
    'class2' => array(
          ),
       ),
       
    'mandarin' => array(
          
    'class1'  => array(
          ),
          
    'class2'  => array(
          )
       )
    ); 
    that is the array where I have all the class textbooks. Now I need to be able to search through it and pick up the text from a specified chapter.
    i.e. I pass on $_GET variables, ['cls'] and ['ch']

    but I can't just do: $textbook[$language][$cls][$ch], because the keys are not the ['ch'] numbers

    also, array_search() does not exactly work, because it doesn't search down multiple arrays.
    Last edited by diabolo; 12-29-2009 at 03:29 PM.

  2. #2
    misson is offline x10 Spammer misson is a jewel in the rough
    Join Date
    Mar 2008
    Location
    Libertatia
    Posts
    2,506

    Re: [PHP] Search a multidimensional array

    What do the contents of $_GET['cls'] and $_GET['ch'] look like? "classN" and an integer? Given that each chapter list in each class array is a range of chapters, you'll need to implement your own search. As long as the chapter ranges are in ascending order (as in the sample), you can use binsearch:

    PHP Code:
    function getChapter($textbook$lang$cls$ch) {
        
    // TODO: add error checking
        
    $cls $textbook[$lang][$cls];
        
    $lo 0;
        
    $hi count($cls);
        
    $mid = ($lo+$hi)>>1;
        do {
            if (
    $ch $cls[$mid][0]) {
                
    $hi $mid;
            } else {
                
    $lo $mid;
            }
            
    $mid = ($lo+$hi) >> 1;
        } while (
    $mid != $lo);
        return 
    $cls[$mid];

    Alternatively, store the chapter list in a DB. For example,
    Code:
    CREATE TABLE classes (
        id INT PRIMARY KEY  AUTO_INCREMENT,
        name VARCHAR(64) DEFAULT NULL,
        level INT,
        lang ENUM('cantonese', 'mandarin') NOT NULL
    ) ENGINE=InnoDB;
    
    /* `sections` is denormalized; in normal form, column `class` 
    belongs in a separate `textbook` table, and column `content` 
    belongs in a `chapters` table.
    */
    CREATE TABLE sections (
        id INT PRIMARY KEY AUTO_INCREMENT,
        start INT NOT NULL, -- starting chapter
        end INT NOT NULL, -- ending chapter
        `range` VARCHAR(32), -- e.g. 'Three - Five'
        label VARCHAR(128), -- short description of chapters
        content TEXT NOT NULL,
        class INT NOT NULL,
        FOREIGN KEY (class) REFERENCES classes (id),
        INDEX (start, end)
    ) ENGINE=InnoDB;
    To get a section:
    Code:
    SELECT sect.start, sect.end, sect.label, sect.content 
        FROM sections AS sect 
        JOIN classes AS cl 
          ON sect.class=cl.id AND sect.class=:class
        WHERE cl.lang=:lang AND sect.start <= :ch AND :ch <= sect.end;
    Of course, if one textbook can be used for multiple classes, you'll have to redesign the schema.

    You might want to create a trigger to prevent sections from overlapping:
    Code:
    DROP TRIGGER IF EXISTS section_nooverlap;
    DELIMITER //
    CREATE TRIGGER section_nooverlap BEFORE INSERT ON sections
    FOR EACH ROW 
    BEGIN
        DECLARE dummy INT;
        IF EXISTS(SELECT id FROM sections AS s 
                      WHERE New.class = s.class
                        AND ((New.start <= s.start AND s.start <= New.end) 
                          OR (New.start <= s.end   AND s.end   <= New.end)))
        THEN 
            SELECT `New section overlaps existing section(s).` INTO dummy 
                FROM sections WHERE sections.id=NEW.id;
        END IF ;
    END //
    DELIMITER ;
    Since the `section` table won't likely be updated often, the trigger will have at most a small impact on the speed of your site.
    Last edited by misson; 12-29-2009 at 04:40 PM.
    Be sure to read all pages linked in this post; they have further information that should prove useful. When asking for help, make sure you follow Eric Raymond's and Jon Skeet's guidelines for prompt, accurate responses. Please answer any questions I ask; they're not rhetorical (probably). Any posted code is intended as illustrative example, rather than a solution to your problem to be copied without alteration. Study it to learn how to write your own solution.
    Misson, not Mission.

  3. #3
    diabolo's Avatar
    diabolo is offline Community Advocate diabolo is on a distinguished road
    Join Date
    Nov 2007
    Location
    Jersey Shore
    Posts
    1,683

    Re: [PHP] Search a multidimensional array

    I was thinking about using a db, but I because Im working on an offline copy(localhost)
    I hate having to change settings and do everything twice once I put it to a production server

    but it would make everything easier,
    so I guess Ill will try one of those, and see how things go
    Last edited by diabolo; 12-29-2009 at 03:31 PM.

  4. #4
    t2t2t's Avatar
    t2t2t is offline x10 Elder t2t2t is an unknown quantity at this point
    Join Date
    Sep 2006
    Location
    Europe, Estonia
    Posts
    690

    Re: [PHP] Search a multidimensional array

    Quote Originally Posted by diabolo View Post
    but I can't just do: $textbook[$language][$cls][$ch], because the keys are not the ['ch'] numbers
    Restructure it then:
    PHP Code:
    <?php
    $textbook 
    = array(
        
    'cantonese' => array(
            
    'class1' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            ),
            
    'class2' => array(
                
    // Follow above
            
    )
        ),
        
    'mandarin' => array(
            
    // Follow above
        
    )
        
    // And so on
    );
    // Example:
    echo $textbook['cantonese']['class1'][3][0].'<br />'.$textbook['cantonese']['class1'][3][1]; // Three - Five<br />Chapter 3 to Chapter 5
    ?>
    This post has been marked spam 52 times.


  5. #5
    misson is offline x10 Spammer misson is a jewel in the rough
    Join Date
    Mar 2008
    Location
    Libertatia
    Posts
    2,506

    Re: [PHP] Search a multidimensional array

    Quote Originally Posted by diabolo View Post
    I was thinking about using a db, but I because Im working on an offline copy(localhost)
    I hate having to change settings and do everything twice once I put it to a production server
    You shouldn't need to do everything twice. Just set up the design server as a mirror of the production server. Alternatively, have a configuration script that sets DB configuration options, such as user, password, database and table names.

    If all you need to do with the data is fetch a single chapter, the binsearch approach should be fine. Any more than that and using a DB is the best choice.

    Quote Originally Posted by t2t2t View Post
    Restructure it then:
    What if $_GET['cls']==1 && $_GET['ch'] == 2? Since Diabolo hasn't clarified the legal values of $_GET['ch'], we can't rule out that case.

    Of course, if it comes down to altering the input format, he could use section numbers rather than chapter numbers, which would simplify both indexing and error checking.
    Last edited by misson; 12-29-2009 at 05:03 PM.
    Be sure to read all pages linked in this post; they have further information that should prove useful. When asking for help, make sure you follow Eric Raymond's and Jon Skeet's guidelines for prompt, accurate responses. Please answer any questions I ask; they're not rhetorical (probably). Any posted code is intended as illustrative example, rather than a solution to your problem to be copied without alteration. Study it to learn how to write your own solution.
    Misson, not Mission.

  6. #6
    t2t2t's Avatar
    t2t2t is offline x10 Elder t2t2t is an unknown quantity at this point
    Join Date
    Sep 2006
    Location
    Europe, Estonia
    Posts
    690

    Re: [PHP] Search a multidimensional array

    Quote Originally Posted by misson View Post
    What if $_GET['cls']==1 && $_GET['ch'] == 2? Since Diabolo hasn't clarified the legal values of $_GET['ch'], we can't rule out that case.

    Of course, if it comes down to altering the input format, he could use section numbers rather than chapter numbers, which would simplify both indexing and error checking.
    That value wasn't mentioned in original post ;). And a simple check for that would be:
    PHP Code:
    if(is_array($textbook['cantonese']['class'.$_GET['cls']][$_GET['ch']])) {
        echo 
    $textbook['cantonese']['class'.$_GET['cls']][$_GET['ch']][0].'<br />'.$textbook['cantonese']['class'.$_GET['cls']][$_GET['ch']][1];
    } else {
        echo 
    'Oopsies!';
    }
    // Example outputs:

    // ?cls=1&ch=3
    // Three - Five<br />Chapter 3 to Chapter 5

    // ?cls=1&ch=4
    // Oopsies! 
    This post has been marked spam 52 times.


  7. #7
    diabolo's Avatar
    diabolo is offline Community Advocate diabolo is on a distinguished road
    Join Date
    Nov 2007
    Location
    Jersey Shore
    Posts
    1,683

    Re: [PHP] Search a multidimensional array

    Quote Originally Posted by t2t2t View Post
    Restructure it then:
    PHP Code:
    <?php
    $textbook 
    = array(
        
    'cantonese' => array(
            
    'class1' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            ),
            
    'class2' => array(
                
    // Follow above
            
    )
        ),
        
    'mandarin' => array(
            
    // Follow above
        
    )
        
    // And so on
    );
    // Example:
    echo $textbook['cantonese']['class1'][3][0].'<br />'.$textbook['cantonese']['class1'][3][1]; // Three - Five<br />Chapter 3 to Chapter 5
    ?>
    I did also try a restructure version of it, but that went haywire after I couldn't figure out how the foreach loops would function

  8. #8
    t2t2t's Avatar
    t2t2t is offline x10 Elder t2t2t is an unknown quantity at this point
    Join Date
    Sep 2006
    Location
    Europe, Estonia
    Posts
    690

    Re: [PHP] Search a multidimensional array

    Here's a small example to show how to loop everything:
    PHP Code:
    <?php
    // Just repeating text for example.
    $textbook = array(
        
    'cantonese' => array(
            
    'class1' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            ),
            
    'class2' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            )
        ),
        
    'mandarin' => array(
            
    'class1' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            ),
            
    'class2' => array(
                
    => array('One - Two''Chapter 1 to Chapter 2''text'),
                
    => array('Three - Five''Chapter 3 to Chapter 5''text'),
                
    => array('Six - Eight''Chapter 6 to Chapter 8''text'),
            )
        )
    );
    ?>
    <!-- Some styling for better understanding -->
    <style type="text/css">
        div {
            margin-left: 2em;
        }
    </style>
    <?php
    foreach($textbook as $lang => $langdata) { // Loop languages
        
    echo '<h2>'.ucfirst($lang).'</h2><div>';
        foreach(
    $langdata as $class => $classdata) { // Loop classes
            
    echo '<h3>'.ucfirst($class).'</h3><div>';
            foreach(
    $classdata as $chapter => $chapterdata) { // Loop chapters
                
    echo '<h4>Chapter '.$chapter.' - '.$chapterdata[0].'</h4><div><span style="font-style: italic;">'.$chapterdata[1].'</span><p>'.$chapterdata[2].'</p></div>';
            }
            echo 
    '</div>';
        }
        echo 
    '</div>';
    }
    ?>
    Example output
    This post has been marked spam 52 times.


  9. #9
    xav0989's Avatar
    xav0989 is offline Community Public Relation xav0989 is just really nice
    Join Date
    Jul 2008
    Location
    ifk
    Posts
    4,438

    Re: [PHP] Search a multidimensional array

    Can't you have a recursive array search?
    Xavier L | Community Public Relations Manager (Free Hosting Support)
    █ Yes, my position is too cool to even exist!
    How am I helping? Rate this post by clicking the icon below! (this is even better than "liking" a post)
    Terms of Service | Acceptable Use Policy | x10Hosting Wiki

  10. #10
    diabolo's Avatar
    diabolo is offline Community Advocate diabolo is on a distinguished road
    Join Date
    Nov 2007
    Location
    Jersey Shore
    Posts
    1,683

    Re: [PHP] Search a multidimensional array

    well here's what I originally had.

    PHP Code:
    function loadClass($dialect$error=NULL) {
       include 
    ROOT.'sources/bits/textbook.php';
       
    $i 0;
       
       foreach (
    $textbookList[$dialect] as $class => $chapters) {
          
    $numClasses count($textbookList[$dialect]);
          
    $rowClass 'row';
             if(
    $i == ($numClasses-1)) { $rowClass 'row lastRow'; }
          
    $html .= '<div class="'.$rowClass.'" id="'.$class.'">';
          
    $html .= '<div class="class">'.$class.'</div>';
          
    $html .= '<div class="chapterContainer">';
             
    $numChapters count($chapters);
             
    $ii 0;
             while(
    $ii $numChapters) {
                
    $html .= '<a href="'.ROOT.'curriculum/'.$dialect.'/textbook.php?cls='.$class.'&ch='.$chapters[$ii]['0'].'"><span class="chapter">'.$chapters[$ii]['1'].'</span></a>';
                
    $ii++;
             }
          
    $html .= '</div>';
          
    $html .= '</div>';
       
    $i++;
       }
    echo 
    $html;   

    I needed to separate it by classes too. but i've started working on the db version so unless someone can come with an awesome breakthrough that requires no brain work for me other than copy+paste, I think im going to work with the db version
    Last edited by diabolo; 12-29-2009 at 06:18 PM.

+ Reply to Thread
Page 1 of 2 12 LastLast

Similar Threads

  1. Replies: 0
    Last Post: 10-10-2009, 05:48 AM
  2. The Ten Search Engine Commandments
    By lhyman in forum Tutorials
    Replies: 10
    Last Post: 09-21-2009, 05:15 AM
  3. [PHP] sorting 2-dimensional array by timestamp-key
    By bonzo meier in forum Programming Help
    Replies: 0
    Last Post: 02-19-2008, 04:28 PM
  4. Can some1 tell me if this is the legal IF 2.0?
    By pensoftware in forum Computers & Technology
    Replies: 9
    Last Post: 04-05-2006, 12:33 PM
  5. [PHP] Dynamic Includes Tutorial
    By Bryon in forum Tutorials
    Replies: 3
    Last Post: 12-16-2005, 01:34 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
x10hosting free hosting for the masses
dedicated servers