Sunday, October 27, 2013

Arrays and Indexers in Phalanger



Today's post is about Arrays and Indexers in Phalanger (PHP). Here below you will find a very easy to follow program, that demonstrate arrays and indexer, by implementing some simple tasks that will make you grasp the idea of those 2 features real quick. The main goal of this post, is not really teaching arrays because, come on, you probably already know "all" about them, in fact, it is more to show you how you do that in Phalanger (PHP), in this case, compared to all other 22 languages on future posts, which essentially, is the real aim behind this blog.

This is the first post of a "dynamic" language implemented for the DLR. You will notice that the code structure its slightly different from previous posts. Besides that, because Phalanger is PHP, it is definitely better to use PHP's array type instead of System\Array, implemented in Phalanger as PhpArray which at the end, stores the data as a Dictionary<object,object>.

By the way, if you missed my most recent post, "New Series - Arrays and Indexers", check it out. It has more details about the following program, and a bunch of definitions for the concepts used on this, and the following, posts. Or you can check my previous posts about arrays in C# and C++ just to compare.

I encourage you to copy the code below and try it yourself, normally, all programs you find in this blog are source code complete, just paste it on your IDE and run it.

There is room for improvement of the code, using generics is one example, but Generics, Collections, lambdas, etc. will have their own "series" of posts.


<?php
namespace PhpArrays 
{    
    use System as S;
    use System\Console;
    use System\Random;
    use System\Text as T;
    
    class Program
    {
        static function Main()
        {            
            /* 
             * An array in PHP is actually an ordered map.
             * implements arrays as Phpp.Runtime.PhpArray class 
             * that internally implements a Dictionary<object,object>.
            */
            
            // Single-dimensional Array(s)  
            self::printTitle("Reverse Array Elements");
            
            // Declare and Initialize Array of Chars  
            $letters = array();  
            $letters[0] = "A";  
            $letters[1] = "E";  
            $letters[2] = "I";  
            $letters[3] = "O";  
            $letters[4] = "U"; 
            
            //print_r($letters);
            self::printArray($letters);
            $inverse_letters = self::reverseChar($letters);  
            self::printArray($inverse_letters);  
            
            self::printTitle("Sort Integer Array Elements");  
            
            // Declare and Initialize Array of Integers   
            $numbers = array ( 10, 8, 3, 1, 5 );  
            self::printArray($numbers);  
            $ordered_numbers = self::bubbleSort($numbers);  
            self::printArray($ordered_numbers);  
            
            self::printTitle("Sort String Array Elements");  
            
            // Declare and Initialize and Array of Strings  
            $names = array (                       
                    "Damian",   
                    "Rogelio",  
                    "Carlos",   
                    "Luis",                       
                    "Daniel"  
                );  
            self::printArray($names);  
            $ordered_names = self::bubbleSort($names);  
            self::printArray($ordered_names);  
            
            // Multi-dimensional Array (Matrix row,column)  
            // in PHP they are the same as Jagged Arrays or "array of arrays"
            
            self::printTitle("Transpose Matrix");  
            
            /* Matrix row=2,col=3 
             * A =  [6  4 24] 
             *      [1 -9  8] 
             */  
            $matrix = array ( array ( 6, 4, 24 ),   
                              array ( 1, -9, 8 ));  
            self::printMatrix($matrix);  
            $transposed_matrix = self::transposeMatrix($matrix);  
            self::printMatrix($transposed_matrix);  
            
            // Jagged Array (Array-of-Arrays)         
            
            self::printTitle("Upper Case Random Array & Graph Number of Elements");  
            
            /*              
             * Creating an array of string arrays using the String.Split method 
             * instead of initializing it manually as follows: 
             *  
             * $text = array (  
             *      array ( "word1", "word2", "wordN" ),  
             *      array ( "word1", "word2", "wordM" ),  
             *      ... 
             *      ); 
             *  
             * Text extract from: "El ingenioso hidalgo don Quijote de la Mancha" 
             *  
             */  
            // using php function explode (split also works)
            $text = array (   
            \explode(" ", "Hoy es el día más hermoso de nuestra vida, querido Sancho;"),  
            \explode(" ", "los obstáculos más grandes, nuestras propias indecisiones;"),  
            \explode(" ", "nuestro enemigo más fuerte, miedo al poderoso y nosotros mismos;"),  
            \explode(" ", "la cosa más fácil, equivocarnos;"),
            \explode(" ", "la más destructiva, la mentira y el egoísmo;"),
            \explode(" ", "la peor derrota, el desaliento;"),
            \explode(" ", "los defectos más peligrosos, la soberbia y el rencor;"),
            \explode(" ", "las sensaciones más gratas, la buena conciencia...")
            );          
            //print_r ($text);
            self::printJaggedArray($text);  
            $text = self::upperCaseRandomArray($text);  // param not by reference
            self::printJaggedArray($text);  
            self::graphJaggedArray($text);  
            
            // Array Exceptions  
            
            self::printTitle("Common Array Exceptions");  
            
            self::printCommonArrayExceptions(NULL);  
            self::printCommonArrayExceptions($text);  
            
            // Accessing Class Array Elements through Indexer  
            
            self::printTitle("Alphabets");  
            
            $vowels = new Alphabet(5);  
            $vowels[0] = 'a';  
            $vowels[1] = 'e';  
            $vowels[2] = 'i';  
            $vowels[3] = 'o';  
            $vowels[4] = 'u';  
            
            //print_r ($vowels);
            
            echo "\nVowels = {" 
                . \implode(",", array($vowels[0], $vowels[1], $vowels[2], $vowels[3], $vowels[4])) 
                . "}\n";                  
            
            $en = new Alphabet("abcdefghijklmnopqrstuvwxyz");  
            echo "English Alphabet = {{$en}}\n";  
  
            echo "Alphabet Extract en[9..19] = {"
                . new Alphabet($en->slice(9, 10))  
                . "}\n";
            
            $word1 = \implode("", array ($en[6], $en[14], $en[14], $en[3]));  
            $word2 = \implode("", array ($en[1], $en[24], $en[4]));  
            $word3 = \implode("", array ($en[4], $en[21], $en[4], $en[17],  
                                         $en[24], $en[14], $en[13], $en[4]));  
  
            echo "\n$word1 $word2, $word3!\n";
  
            \fgets(STDIN);

            return 0;
        }
        
        static function reverseChar($arr)
        {              
            $reversed = array();  
            for ($i = 0, $j = \count($arr) - 1; $j >= 0; $i++, $j--)  
            {
                $reversed[$i] = $arr[$j]; 
            }
            return $reversed;  
            // or: return \array_reverse($arr);
        }  
        
        static function bubbleSort($arr)  
        {  
            $swap = 0;  
            for ($i = \count($arr) - 1; $i > 0; $i--)  
            {  
                for ($j = 0; $j < $i; $j++)  
                {  
                    // if ($arr[$j][0] > $arr[$j + 1][0])  
                    if (\is_numeric($arr[$j]) ? 
                        $arr[$j] > $arr[$j + 1] : 
                        $arr[$j][0] > $arr[$j + 1][0])  
                    {  
                        $swap = $arr[$j];  
                        $arr[$j] = $arr[$j + 1];  
                        $arr[$j + 1] = $swap;  
                    }  
                }  
            }  
            return $arr;  
        }  
                                    
        static function transposeMatrix($m)  
        {  
            /* Transposing a Matrix 2,3  
             *  
             * A =  [6  4 24]T [ 6  1]  
             *      [1 -9  8]  [ 4 -9] 
             *                 [24  8] 
             */
            $transposed = array();  
            for ($i = 0; $i < \count($m); $i++)  
            {  
                for ($j = 0; $j < \count($m[0]); $j++)  
                {  
                    $transposed[$j][$i] = $m[$i][$j];                  
                }  
            }  
            return $transposed;  
        }  
        
        static function upperCaseRandomArray($arr)  
        {  
            $r = new Random();  
            $i = $r->Next(0, \count($arr) - 1);  
            for ($j = 0; $j < \count($arr[$i]); $j++)  
            {
                $arr[$i][$j] = \strtoupper($arr[$i][$j]);  
            }
            return $arr;
        }  
        
        static function printArray($arr)  
        {  
            echo "\nPrint Array Content " . $arr->GetType()->Name . "\n";
            
            for ($i = 0; $i < \count($arr); $i++)  
            {
                Console::WriteLine(" array [{0,2}] = {1,2} ", $i, $arr[$i]);          
            }
        }  
        
        static function printMatrix($m)  
        {  
            echo "\nPrint Matrix Content " . $m->GetType()->Name 
            . "[" . \count($m) . "," . \count($m[0]) . "]\n";        
            
            for ($i = 0; $i < \count($m); $i++)  
            {
                for ($j = 0; $j < \count($m[0]); $j++)  
                {
                    Console::WriteLine(" array [{0,2},{1,2}] = {2,2} ", $i, $j, $m[$i][$j]);  
                }
            }
        }  
        
        static function graphJaggedArray($arr)  
        {  
            /* When using Arrays, we can use foreach instead of for:  
             *  
             * for (int i = 0; i <= arr.Length - 1; i++) 
             *   for (int j = 0; j <= arr.Length - 1; j++)                 
             *  
             */  
            echo "\nPrint Text Content " . $arr->GetType()->Name . "\n";  
            $lineCount = 1;  
            foreach ($arr as $s)  
            {  
                Console::Write("Line{0,2}|", $lineCount);  
                foreach ($s as $w)  
                {  
                    Console::Write("{0,3}", '*');  
                }  
                echo " (" . \count($s) . ")\n";  
                $lineCount++;  
            }  
        }  
        
        static function printJaggedArray($arr)  
        {          
            echo "\nPrint Jagged Array Content " . $arr->GetType()->Name . "\n";  
            for ($i = 0; $i < \count($arr); $i++)  
            {  
                $line = new T\StringBuilder();  
                for ($j = 0; $j < \count($arr[$i]); $j++)
                {
                    $line->Append(" " . $arr[$i][$j]);  
                }
                if ($line->ToString() == \strtoupper($line->ToString()))  
                {
                    $line->Append(" <-- [UPPERCASED]");  
                }
                echo $line . "\n";  
            }  
        }  

        static function printCommonArrayExceptions($arr)  
        {  
            // there is a bug throwing System\Exception(s) in Phalanger.
            // but apparently it has been quickly fixed after reported.
            try  
            {  
                /* Throwing System\Exception(s) do not get caught in
                 * the catch, instead they give an error message and 
                 * continue executing. i.e.
                 * throw new S\NullReferenceException("");                    
                 * throw new S\Exception("");
                */
                
                if (\is_null($arr))
                {
                    throw new \ErrorException(
                        "Object reference not set to an instance of an object.", 
                        0, \E_ERROR);                    
                }
                if (!isset($arr[100][100]))
                {
                    throw new \OutOfRangeException(
                        "Index was outside the bounds of the array.", 0);
                }      
            }  
            catch (\OutOfRangeException $ex)  
            {  
                echo "\nException: OutOfRangeException\n" . 
                    $ex->getMessage() . "\n";  
            } 
            catch (\ErrorException $ex)  
            {  
                echo "\nException: ErrorException " .
                    $ex->getSeverity() . "\n" . $ex->getMessage() . "\n";                
            }             
            /*catch (S\Exception $ex)
            {
                echo "\nException: ", "Exception", 
                    $ex->getMessage(), "\n";  
            }*/
        }  
        
        static function printTitle(string $message)
        {
            echo "\n";
            echo \str_repeat("=", 54) . "\n";
            echo $message . "\n";
            echo \str_repeat("=", 54) . "\n";
        }
    }

    [\Export]    
    class Alphabet implements \ArrayAccess   
    {    
        // Array Field
        private $letters = array();
        
        // Indexer Get/Set methods
        // Implementing ArrayAccess methods
        public function offsetSet($offset, $value) {
            if (\is_null($offset)) 
            {
                $this->letters[] = $value;
            } else 
            {
                $this->letters[$offset] = \strtoupper($value);
            }
        }
        public function offsetExists($offset) {
            return isset($this->letters[$offset]);
        }
        public function offsetUnset($offset) {
            unset($this->letters[$offset]);
        }
        public function offsetGet($offset) {
            return isset($this->letters[$offset]) ? $this->letters[$offset] : NULL;
        }
        
        // Read-Only Property  
        public function getLength()
        {  
            return \count($this->letters); 
        }  
        
        // Constructor 
        // No Overloaded Constructors support in (PHP) Phalanger 
        public function __construct($param = NULL)    
        {   
            // int $size
            if(\is_numeric($param))
            {
                $this->letters = \array_pad($this->letters, $size, ' '); 
            }
            // string $list
            else if(\is_string($param))
            {
                $this->letters = \str_split(\strtoupper($param));
            }
            // array $list
            else if(\is_array($param))
            {
                $this->letters = $param;
            }
            else 
            {
                $this->letters = NULL;
            }
        }    
        
        // Overridden Method
        public function __toString()    
        {    
            return \join(",", $this->letters); 
        }
        
        // Method  
        public function slice($start, $length)  
        {  
            return \array_slice($this->letters, $start, $length);              
        }  
    }    
}
?>


The output:






















































































Voilà, that's it. Next post in the following days.

No comments:

Post a Comment