function pleac_Processing_All_Files_in_a_Directory()
{
    // Conventional POSIX-like approach to directory traversal
    $dirname = '/usr/bin/';
    ($dirhdl = opendir($dirname)) || die("Couldn't open {$dirname}\n");
    while (($file = readdir($dirhdl)) !== FALSE) {
        // ... do something with $dirname/$file
        // ...
    }
    closedir($dirhdl);
    // ------------
    // Newer [post PHP 4], 'applicative' approach - an array of filenames is
    // generated that may be processed via external loop ...
    $dirname = '/usr/bin/';
    foreach (scandir($dirname) as $file) {
        // ... do something with $dirname/$file
        // ...
    }
    // .. or, via callback application, perhaps after massaging by one of the
    // 'array' family of functions [also uses, 'array_update', from earlier section]
    $newlist = array_update(array_reverse(scandir($dirname)), create_function('$filelist, $file', ' ; '), array());
    // And don't forget that the old standby, 'glob', that returns an array of
    // paths filtered using the Bourne Shell-based wildcards, '?' and '*', is
    // also available
    foreach (glob($dirname . '*') as $path) {
        // ... do something with $path
        // ...
    }
    // ----------------------------
    // Uses, 'isTextFile', from an earlier section
    $dirname = '/usr/bin/';
    echo "Text files in {$dirname}:\n";
    foreach (scandir($dirname) as $file) {
        // Take care when constructing paths to ensure cross-platform operability
        $path = $dirname . $file;
        if (is_file($path) && isTextFile($path)) {
            echo $path . "\n";
        }
    }
    // ----------------------------
    function plain_files($dirname)
    {
        ($dirlist = glob($dirname . '*')) || die("Couldn't glob {$dirname}\n");
        // Pass function name directly if only a single function performs filter test
        return array_filter($dirlist, 'is_file');
        // Use, 'create_function', if a multi-function test is needed
        //
        // return array_filter($dirlist, create_function('$path', 'return is_file($path);'));
        //
    }
    // ------------
    foreach (plain_files('/tmp/') as $path) {
        echo $path . "\n";
    }
}
Example #2
0
 public function testArrayUpdateMissing()
 {
     $array = array_update($this->array, 42, function ($v) {
         return $v + 1;
     });
     $this->assertSame($this->array, $array);
     $array = array_update($this->array, 3, function ($v) {
         return $v + 1;
     });
     $this->assertSame($this->array, $array);
 }
function pleac_Finding_the_First_List_Element_That_Passes_a_Test()
{
    // This section illustrates various 'find first' techniques. The Perl examples all use an
    // explicit loop and condition testing [also repeated here]. This is the simplest, and
    // [potentially] most efficient approach because the search can be terminated as soon as a
    // match is found. However, it is worth mentioning a few alternatives:
    // * 'array_search' performs a 'find first' using the element value rather than a condition
    //    check, so isn't really applicable here
    // * 'array_filter', whilst using a condition check, actually performs a 'find all', though
    //   all but the first returned element can be discarded. This approach is actually less error
    //   prone than using a loop, but the disadvantage is that each element is visited: there is no
    //   means of terminating the search once a match has been found. It would be nice if this
    //   function were to have a third parameter, a Boolean flag indicating whether to traverse
    //   the whole array, or quit after first match [next version, maybe :) ?]
    $found = FALSE;
    foreach ($array as $item) {
        // Not found - skip to next item
        if (!$criterion) {
            continue;
        }
        // Found - save and leave
        $match = $item;
        $found = TRUE;
        break;
    }
    if ($found) {
        // do something with $match
    } else {
        // not found
    }
    // ------------
    function predicate($element)
    {
        if (criterion) {
            return TRUE;
        }
        return FALSE;
    }
    $match = array_slice(array_filter($array, 'predicate'), 0, 1);
    if ($match) {
        // do something with $match[0]
    } else {
        // $match is empty - not found
    }
    // ----------------------------
    class Employee
    {
        public $name, $age, $ssn, $salary;
        public function __construct($name, $age, $ssn, $salary, $category)
        {
            $this->name = $name;
            $this->age = $age;
            $this->ssn = $ssn;
            $this->salary = $salary;
            $this->category = $category;
        }
    }
    // ------------
    $employees = array(new Employee('sdf', 27, 12345, 47000, 'Engineer'), new Employee('ajb', 32, 12376, 51000, 'Programmer'), new Employee('dgh', 31, 12355, 45000, 'Engineer'));
    // ------------
    function array_update($arr, $lambda, $updarr)
    {
        foreach ($arr as $key) {
            $lambda($updarr, $key);
        }
        return $updarr;
    }
    function highest_salaried_engineer(&$arr, $employee)
    {
        static $highest_salary = 0;
        if ($employee->category == 'Engineer') {
            if ($employee->salary > $highest_salary) {
                $highest_salary = $employee->salary;
                $arr[0] = $employee;
            }
        }
    }
    // ------------
    // 'array_update' custom function is modelled on 'array_reduce' except that it allows the
    // return of an array, contents and length of which are entirely dependant on what the
    // callback function does. Here, it is logically working in a 'find first' capacity
    $highest_salaried_engineer = array_update($employees, 'highest_salaried_engineer', array());
    echo 'Highest paid engineer is: ' . $highest_salaried_engineer[0]->name . "\n";
}
function pleac_Sorting_a_List_by_Computable_Field()
{
    // Tasks in this section would typically use the PHP 'usort' family of functions
    // which are used with a comparator function so as to perform custom comparisions.
    // A significant difference from the Perl examples is that these functions are
    // inplace sorters, so it is the original array that is modified. Where this must
    // be prevented a copy of the array can be made and sorted
    function comparator($left, $right)
    {
        // Compare '$left' with '$right' returning result
    }
    // ------------
    $ordered = array_slice($unordered);
    usort($ordered, 'comparator');
    // ----------------------------
    // The Perl example looks like it is creating a hash using computed values as the key,
    // array values as the value, sorting on the computed key, then extracting the sorted
    // values and placing them back into an array
    function compute($value)
    {
        // Return computed value utilising '$value'
    }
    // ------------
    // Original numerically-indexed array [sample data used]
    $unordered = array(5, 3, 7, 1, 4, 2, 6);
    // Create hash using 'compute' function to generate the keys. This example assumes that
    // each value in the '$unordered' array is used in generating the corresponding '$key'
    foreach ($unordered as $value) {
        $precomputed[compute($value)] = $value;
    }
    // Copy the hash, and sort it by key
    $ordered_precomputed = array_slice($precomputed, 0);
    ksort($ordered_precomputed);
    // Extract the values of the hash in current order placing them in a new numerically-indexed
    // array
    $ordered = array_values($ordered_precomputed);
    // ----------------------------
    // As above, except uses 'array_update' and 'accum' to help create hash
    function array_update($arr, $lambda, $updarr)
    {
        foreach ($arr as $key) {
            $lambda($updarr, $key);
        }
        return $updarr;
    }
    function accum(&$arr, $value)
    {
        $arr[compute($value)] = $value;
    }
    // ------------
    function compute($value)
    {
        // Return computed value utilising '$value'
    }
    // ------------
    // Original numerically-indexed array [sample data used]
    $unordered = array(5, 3, 7, 1, 4, 2, 6);
    // Create hash
    $precomputed = array_update($unordered, 'accum', array());
    // Copy the hash, and sort it by key
    $ordered_precomputed = array_slice($precomputed, 0);
    ksort($ordered_precomputed);
    // Extract the values of the hash in current order placing them in a new numerically-indexed
    // array
    $ordered = array_values($ordered_precomputed);
    // ----------------------------
    class Employee
    {
        public $name, $age, $ssn, $salary;
        public function __construct($name, $age, $ssn, $salary)
        {
            $this->name = $name;
            $this->age = $age;
            $this->ssn = $ssn;
            $this->salary = $salary;
        }
    }
    // ------------
    $employees = array(new Employee('sdf', 27, 12345, 47000), new Employee('ajb', 32, 12376, 51000), new Employee('dgh', 31, 12355, 45000));
    // ------------
    $ordered = array_slice($employees, 0);
    usort($ordered, create_function('$left, $right', 'return $left->name > $right->name;'));
    // ------------
    $sorted_employees = array_slice($employees, 0);
    usort($sorted_employees, create_function('$left, $right', 'return $left->name > $right->name;'));
    $bonus = array(12376 => 5000, 12345 => 6000, 12355 => 0);
    foreach ($sorted_employees as $employee) {
        echo "{$employee->name} earns \${$employee->salary}\n";
    }
    foreach ($sorted_employees as $employee) {
        if ($amount = $bonus[$employee->ssn]) {
            echo "{$employee->name} got a bonus of: \${$amount}\n";
        }
    }
    // ------------
    $sorted = array_slice($employees, 0);
    usort($sorted, create_function('$left, $right', 'return $left->name > $right->name || $left->age != $right->age;'));
    // ----------------------------
    // PHP offers a swag of POSIX functions for obtaining user information [i.e. they all read
    // the '/etc/passwd' file for the relevant infroamtion], and it is these that should rightly
    // be used for this purpose. However, since the intent of this section is to illustrate array
    // manipulation, these functions won't be used. Instead a custom function mimicing Perl's
    // 'getpwent' function will be implemented so the code presented here can more faithfully match
    // the Perl code
    function get_pw_entries()
    {
        function normal_users_only($e)
        {
            $entry = split(':', $e);
            return $entry[2] > 100 && $entry[2] < 32768;
        }
        foreach (array_filter(file('/etc/passwd'), 'normal_users_only') as $entry) {
            $users[] = split(':', trim($entry));
        }
        return $users;
    }
    // ------------
    $users = get_pw_entries();
    usort($users, create_function('$left, $right', 'return $left[0] > $right[0];'));
    foreach ($users as $user) {
        echo "{$user[0]}\n";
    }
    // ----------------------------
    $names = array('sdf', 'ajb', 'dgh');
    $sorted = array_slice($names, 0);
    usort($sorted, create_function('$left, $right', 'return substr($left, 1, 1) > substr($right, 1, 1);'));
    // ------------
    $strings = array('bbb', 'aa', 'c');
    $sorted = array_slice($strings, 0);
    usort($sorted, create_function('$left, $right', 'return strlen($left) > strlen($right);'));
    // ----------------------------
    function array_update($arr, $lambda, $updarr)
    {
        foreach ($arr as $key) {
            $lambda($updarr, $key);
        }
        return $updarr;
    }
    function accum(&$arr, $value)
    {
        $arr[strlen($value)] = $value;
    }
    // ----
    $strings = array('bbb', 'aa', 'c');
    $temp = array_update($strings, 'accum', array());
    ksort($temp);
    $sorted = array_values($temp);
    // ----------------------------
    function array_update($arr, $lambda, $updarr)
    {
        foreach ($arr as $key) {
            $lambda($updarr, $key);
        }
        return $updarr;
    }
    function accum(&$arr, $value)
    {
        if (preg_match('/(\\d+)/', $value, $matches)) {
            $arr[$matches[1]] = $value;
        }
    }
    // ----
    $fields = array('b1b2b', 'a4a', 'c9', 'ddd', 'a');
    $temp = array_update($fields, 'accum', array());
    ksort($temp);
    $sorted_fields = array_values($temp);
}
Example #5
0
 function array_update($arr, $ins)
 {
     if (is_array($arr) && is_array($ins)) {
         foreach ($ins as $k => $v) {
             if (isset($arr[$k]) && is_array($v) && is_array($arr[$k])) {
                 $arr[$k] = array_update($arr[$k], $v);
             } else {
                 $arr[$k] = $v;
             }
         }
     } elseif (!is_array($arr) && (strlen($arr) == 0 || $arr == 0)) {
         $arr = $ins;
     }
     return $arr;
 }
function pleac_Recognizing_Two_Names_for_the_Same_File()
{
    function makeDevInodePair($filename)
    {
        if (!($fs = @stat($filename))) {
            return FALSE;
        }
        return strval($fs['dev'] . $fs['ino']);
    }
    // ------------
    function do_my_thing($filename)
    {
        // Using a global variable to mimic Perl example, but could easily have passed
        // '$seen' as an argument
        global $seen;
        $devino = makeDevInodePair($filename);
        // Process $filename if it has not previously been seen, else just increment
        if (!isset($seen[$devino])) {
            // ... process $filename ...
            // Set initial count
            $seen[$devino] = 1;
        } else {
            // Otherwise, just increment the count
            $seen[$devino] += 1;
        }
    }
    // ----
    // Simple example
    $seen = array();
    do_my_thing('/tmp/old');
    do_my_thing('/tmp/old');
    do_my_thing('/tmp/old');
    do_my_thing('/tmp/new');
    foreach ($seen as $devino => $count) {
        echo "{$devino} -> {$count}\n";
    }
    // ------------
    // A variation on the above avoiding use of global variables, and illustrating use of
    // easily-implemented 'higher order' techniques
    // Helper function loosely modelled on, 'array_reduce', but using an array as
    // 'accumulator', which is returned on completion
    function array_update($arr, $lambda, $updarr)
    {
        foreach ($arr as $key) {
            $lambda($updarr, $key);
        }
        return $updarr;
    }
    function do_my_thing(&$seen, $filename)
    {
        if (!array_key_exists($devino = makeDevInodePair($filename), $seen)) {
            // ... processing $filename ...
            // Update $seen
            $seen[$devino] = 1;
        } else {
            // Update $seen
            $seen[$devino] += 1;
        }
    }
    // ----
    // Simple example
    $files = array('/tmp/old', '/tmp/old', '/tmp/old', '/tmp/new');
    // Could do this ...
    $seen = array();
    array_update($files, 'do_my_thing', &$seen);
    // or this:
    $seen = array_update($files, 'do_my_thing', array());
    // or a 'lambda' could be used:
    array_update($files, create_function('$seen, $filename', '... code not shown ...'), &$seen);
    foreach ($seen as $devino => $count) {
        echo "{$devino} -> {$count}\n";
    }
    // ----------------------------
    $files = glob('/tmp/*');
    define(SEP, ';');
    $seen = array();
    foreach ($files as $filename) {
        if (!array_key_exists($devino = makeDevInodePair($filename), $seen)) {
            $seen[$devino] = $filename;
        } else {
            $seen[$devino] = $seen[$devino] . SEP . $filename;
        }
    }
    $devino = array_keys($seen);
    sort($devino);
    foreach ($devino as $key) {
        echo $key . ':';
        foreach (split(SEP, $seen[$key]) as $filename) {
            echo ' ' . $filename;
        }
        echo "\n";
    }
}