Viewed   57 times

How do you verify an array contains only values that are integers?

I'd like to be able to check an array and end up with a boolean value of true if the array contains only integers and false if there are any other characters in the array. I know I can loop through the array and check each element individually and return true or false depending on the presence of non-numeric data:

For example:

$only_integers = array(1,2,3,4,5,6,7,8,9,10);
$letters_and_numbers = array('a',1,'b',2,'c',3);

function arrayHasOnlyInts($array)
{
    foreach ($array as $value)
    {
        if (!is_int($value)) // there are several ways to do this
        {
             return false;
        }
    }
    return true;
}

$has_only_ints = arrayHasOnlyInts($only_integers ); // true
$has_only_ints = arrayHasOnlyInts($letters_and_numbers ); // false

But is there a more concise way to do this using native PHP functionality that I haven't thought of?

Note: For my current task I will only need to verify one dimensional arrays. But if there is a solution that works recursively I'd be appreciative to see that to.

 Answers

4
$only_integers       === array_filter($only_integers,       'is_int'); // true
$letters_and_numbers === array_filter($letters_and_numbers, 'is_int'); // false

It would help you in the future to define two helper, higher-order functions:

/**
 * Tell whether all members of $array validate the $predicate.
 *
 * all(array(1, 2, 3),   'is_int'); -> true
 * all(array(1, 2, 'a'), 'is_int'); -> false
 */
function all($array, $predicate) {
    return array_filter($array, $predicate) === $array;
}

/**
 * Tell whether any member of $array validates the $predicate.
 *
 * any(array(1, 'a', 'b'),   'is_int'); -> true
 * any(array('a', 'b', 'c'), 'is_int'); -> false
 */
function any($array, $predicate) {
    return array_filter($array, $predicate) !== array();
}
Tuesday, November 1, 2022
1

Actually, this can be done. Through a php extension.

File: config.m4

PHP_ARG_ENABLE(test, whether to enable test Extension support, [ --enable-test   Enable test ext support])

if test "$PHP_TEST" = "yes"; then
  AC_DEFINE(HAVE_TEST, 1, [Enable TEST Extension])
  PHP_NEW_EXTENSION(test, test.c, $ext_shared)
fi

File: php_test.h

#ifndef PHP_TEST_H
#define PHP_TEST_H 1

#define PHP_TEST_EXT_VERSION "1.0"
#define PHP_TEST_EXT_EXTNAME "test"

PHP_FUNCTION(getaddress4);
PHP_FUNCTION(getaddress);

extern zend_module_entry test_module_entry;
#define phpext_test_ptr &test_module_entry

#endif

File: test.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_test.h"

ZEND_BEGIN_ARG_INFO_EX(func_args, 1, 0, 0)
ZEND_END_ARG_INFO()

static function_entry test_functions[] = {
    PHP_FE(getaddress4, func_args)
    PHP_FE(getaddress, func_args)
    {NULL, NULL, NULL}
};

zend_module_entry test_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_TEST_EXT_EXTNAME,
    test_functions,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
#if ZEND_MODULE_API_NO >= 20010901
    PHP_TEST_EXT_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_TEST
ZEND_GET_MODULE(test)
#endif

PHP_FUNCTION(getaddress4)
{
    zval *var1;
    zval *var2;
    zval *var3;
    zval *var4;
    char r[500];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aaaa", &var1, &var2, &var3, &var4) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "n%p - %p - %p - %pn%p - %p - %p - %p", var1, var2, var3, var4, Z_ARRVAL_P(var1), Z_ARRVAL_P(var2), Z_ARRVAL_P(var3), Z_ARRVAL_P(var4) );
    RETURN_STRING(r, 1);
}

PHP_FUNCTION(getaddress)
{
    zval *var;
    char r[100];
    if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &var) == FAILURE ) {
      RETURN_NULL();
    }
    sprintf(r, "%p", Z_ARRVAL_P(var));
    RETURN_STRING(r, 1);
}

Then all you have to do is phpize it, config it, and make it. Add a "extension=/path/to/so/file/modules/test.so" to your php.ini file. And finally, restart the web server, just in case.

<?php
  $x = array("123"=>"123");
  $w = $x;
  $y = $x;
  $z = &$x;
  var_dump(getaddress4($w,$x,$y,$z));
  var_dump(getaddress($w));
  var_dump(getaddress($x));
  var_dump(getaddress($y));
  var_dump(getaddress($z));
?>

Returns(at least for me, your memory addresses will probably be different)

string '
0x9efeb0 - 0x9effe0 - 0x9ef8c0 - 0x9efeb0
0x9efee0 - 0x9f0010 - 0x9ed790 - 0x9efee0' (length=84)

string '0x9efee0' (length=8)

string '0x9f0010' (length=8)

string '0x9ed790' (length=8)

string '0x9efee0' (length=8)

Thanks to Artefacto for pointing this out, but my original code was passing the arrays by value, so thereby was recreating arrays including the referenced-one, and giving you bad memory values. I have since changed the code to force all params to be passed by reference. This will allow references, arrays, and object, to be passed in unmolested by the php engine. $w/$z are the same thing, but $w/$x/$y are not. The old code, actually showed the reference breakage and the fact that the memory addresses would change or match when all variables were passed in vs multiple calls to the same function. This was because PHP would reuse the same memory when doing multiple calls. Comparing the results of the original function would be useless. The new code should fix this problem.

FYI - I'm using php 5.3.2.

Sunday, September 4, 2022
 
sk0x50
 
3

You can try below code to merge array. Code generates desired output required to you. I have used sample array as given by you:

<?php
    $arr1=array(
        "384"=>array("name"=>"SomeMovieName1","age"=>"12.2 hrs","IMDBLink"=>"","IMDBRating"=>"", "coverArt"=>""),
        "452"=>array("name"=>"SomeMovieName2","age"=>"15.2 hrs","IMDBLink"=>"","IMDBRating"=>"", "coverArt"=>""),
        "954"=>array("name"=>"SomeMovieName3","age"=>"4.2 hrs","IMDBLink"=>"","IMDBRating"=>"", "coverArt"=>"")
    );
    $arr2=array(
       "384" => array("IMDBLink" => "7.2", "IMDBRating" => "http://www.imdb.com/LinkToMovie1", "coverArt" => "http://www.SomeLinkToCoverArt.com/1"),
       "452" => array("IMDBLink" => "5","IMDBRating" => "http://www.imdb.com/LinkToMovie2", "coverArt" => "http://www.SomeLinkToCoverArt.com/2"),
       "954"=>array("IMDBLink" => "8","IMDBRating" => "http://www.imdb.com/LinkToMovie3", "coverArt" => "http://www.SomeLinkToCoverArt.com/3")
    );
    $arr3 = array();
    foreach($arr1 as $key=>$val)
    {
         $arr3[] = array_merge($val, $arr2[$key]);
    }
    echo "<pre>";
    print_r($arr3);
?>
Tuesday, September 13, 2022
3

'files' already tells you whats in the directory. Just check it:

for dirpath, dirnames, files in os.walk('.'):
    if files:
        print(dirpath, 'has files')
    if not files:
        print(dirpath, 'is empty')
Friday, August 26, 2022
5

It looks like a generic abstraction, let's open Enumerable:

module Enumerable
  def sorted?
    each_cons(2).all? { |a, b| (a <=> b) <= 0 }
  end
end

[["a", 3], ["b", 53],["c", 2]].sorted? #=> true

Notice that we have to write (a <=> b) <= 0 instead of a <= b because there are classes that support <=> but not the comparator operators (i.e. Array), since they do not include the module Comparable.

You also said you'd like to have the ability "to check for order based on some arbitrary parameter":

module Enumerable  
  def sorted_by?
    each_cons(2).all? { |a, b| ((yield a) <=> (yield b)) <= 0 }    
  end
end

[["a", 3], ["b", 1], ["c", 2]].sorted_by? { |k, v| v } #=> false

Using lazy enumerables (Ruby >= 2.1), we can reuse Enumerable#sorted?:

module Enumerable  
  def sorted_by?(&block)
    lazy.map(&block).sorted?
  end
end
Friday, November 18, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :