कैसे जांचें कि PHP सरणी सहयोगी या अनुक्रमिक है या नहीं?




arrays (24)

In my opinion, an array should be accepted as associative if any of its keys is not integer eg float numbers and empty string ''.

Also non-sequenced integers has to be seen as associative like (0,2,4,6) because these kind of arrays cannot be used with for loops by this way:

$n =count($arr);
for($i=0,$i<$n;$i++) 

The second part of the function below does check if the keys are indexed or not.It also works for keys with negative values. For example (-1,0,1,2,3,4,5)

count() = 7 , max = 5, min=-1



if( 7 == (5-(-1)+1 ) // true
    return false; // array not associative


/** 
 * isAssoc Checks if an array is associative
 * @param $arr reference to the array to be checked
 * @return bool 
 */     
function IsAssoc(&$arr){
    $keys= array_keys($arr);
    foreach($keys as $key){
        if (!is_integer($key))
            return true;
    }
    // if all keys are integer then check if they are indexed
    if(count($arr) == (max($keys)-min($keys)+1))
        return false;
    else
        return true;
}

PHP सभी सरणी को सहयोगी के रूप में मानता है, इसलिए कोई भी अंतर्निहित कार्य नहीं है। क्या कोई भी यह जांचने के लिए एक काफी कुशल तरीका सुझा सकता है कि किसी सरणी में केवल संख्यात्मक कुंजी है या नहीं?

असल में, मैं इसके बीच अंतर करने में सक्षम होना चाहता हूं:

$sequentialArray = array('apple', 'orange', 'tomato', 'carrot');

और इस:

$assocArray = array('fruit1' => 'apple', 
                    'fruit2' => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

आपने दो प्रश्न पूछे हैं जो काफी समकक्ष नहीं हैं:

  • सबसे पहले, यह निर्धारित करने के लिए कि किसी सरणी में केवल संख्यात्मक कुंजी हैं या नहीं
  • दूसरा, यह निर्धारित करने के लिए कि किसी सरणी में 0 से शुरू होने वाली अनुक्रमिक संख्यात्मक कुंजी है या नहीं

गौर करें कि आपको इनमें से कौन सा व्यवहार वास्तव में चाहिए। (ऐसा हो सकता है कि या तो आपके उद्देश्यों के लिए किया जाएगा।)

पहला सवाल (बस जांच रहा है कि सभी चाबियाँ संख्यात्मक हैं) कप्तान कुरो द्वारा अच्छी तरह से उत्तर दिया जाता है ।

दूसरे प्रश्न के लिए (जांच करें कि सरणी शून्य-अनुक्रमित और अनुक्रमिक है), आप निम्न फ़ंक्शन का उपयोग कर सकते हैं:

function isAssoc(array $arr)
{
    if (array() === $arr) return false;
    return array_keys($arr) !== range(0, count($arr) - 1);
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false
var_dump(isAssoc(array("1" => 'a', "0" => 'b', "2" => 'c'))); // true
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true

यह फ़ंक्शन संभाल सकता है:

  • सूचकांक में छेद के साथ सरणी (उदाहरण के लिए 1,2,4,5,8,10)
  • सरणी "0x" कुंजी के साथ: उदाहरण कुंजी '08' सहयोगी है जबकि कुंजी '8' अनुक्रमिक है।

विचार सरल है: यदि कुंजी में से एक पूर्णांक नहीं है, तो यह सहयोगी सरणी है, अन्यथा यह अनुक्रमिक है।

function is_asso($a){
    foreach(array_keys($a) as $key) {if (!is_int($key)) return TRUE;}
    return FALSE;
}

xarray PHP एक्सटेंशन का उपयोग करके

आप इसे बहुत तेज़ कर सकते हैं (PHP 5.6 में लगभग 30+ गुना तेज):

if (array_is_indexed($array)) {  }

या:

if (array_is_assoc($array)) {  }

मुझे लगता है कि 'यदि कोई सरणी सहयोगी या संख्यात्मक है' जांचने के लिए निम्नलिखित दो कार्य करने का सबसे अच्छा तरीका है। चूंकि 'न्यूमेरिक' का मतलब केवल संख्यात्मक कुंजी या केवल अनुक्रमिक संख्यात्मक कुंजी हो सकता है, दो कार्य नीचे सूचीबद्ध हैं जो किसी भी स्थिति की जांच करते हैं:

function is_indexed_array(&$arr) {
  for (reset($arr); is_int(key($arr)); next($arr));
  return is_null(key($arr));
}

function is_sequential_array(&$arr, $base = 0) {
  for (reset($arr), $base = (int) $base; key($arr) === $base++; next($arr));
  return is_null(key($arr));
}

पहला फ़ंक्शन जांचता है कि प्रत्येक कुंजी एक पूर्णांक मान है या नहीं। दूसरा फ़ंक्शन जांचता है कि प्रत्येक कुंजी एक पूर्णांक मान है और इसके अतिरिक्त चेक करता है कि सभी चाबियाँ अनुक्रमिक $ बेस से शुरू होती हैं, जो 0 तक डिफ़ॉल्ट होती है और यदि आपको किसी अन्य मूल मान को निर्दिष्ट करने की आवश्यकता नहीं है तो इस प्रकार छोड़ा जा सकता है। कुंजी ($ my_array) शून्य को वापस लौटाता है यदि रीड पॉइंटर सरणी के अंत से पहले स्थानांतरित हो जाता है, जो कि लूप के लिए समाप्त होता है और लूप लौटने के बाद कथन देता है यदि सभी कुंजी पूर्णांक होती हैं। यदि नहीं, तो लूप समय-समय पर समाप्त होता है क्योंकि एक कुंजी प्रकार स्ट्रिंग है, और लूप के बाद कथन गलत हो जाएगा। इसके बाद का दूसरा कार्य प्रत्येक तुलना के बाद एक से $ आधार जोड़ता है, यह जांचने में सक्षम होने के लिए कि अगली कुंजी सही मान का है या नहीं। सख्त तुलना यह भी जांचती है कि कुंजी प्रकार पूर्णांक है या नहीं। लूप के पहले खंड में $ बेस = (int) $ बेस भाग छोड़ा जा सकता है जब $ बेस छोड़ा जाता है या यदि आप सुनिश्चित करते हैं कि इसे केवल एक पूर्णांक का उपयोग करने के लिए कहा जाता है। लेकिन चूंकि मैं सभी के लिए निश्चित नहीं हो सकता, मैंने इसे छोड़ दिया। कथन केवल एक बार निष्पादित किया जाता है, वैसे भी। मुझे लगता है कि ये सबसे कुशल समाधान हैं:

  • मेमोरी वार: डेटा या कुंजी श्रेणियों की कोई प्रतिलिपि नहीं। Array_values ​​या array_keys करना छोटा (कम कोड) प्रतीत हो सकता है लेकिन ध्यान दें कि जब आप कॉल करते हैं तो पृष्ठभूमि में क्या चल रहा है। हां कुछ अन्य समाधानों की तुलना में अधिक (दृश्यमान) बयान हैं, लेकिन यह मायने रखता है, क्या यह नहीं है?
  • समयवार: इस तथ्य के अलावा कि डेटा और / या चाबियों को कॉपी / निकालने में भी समय लगता है, यह समाधान एक foreach करने से अधिक कुशल है। फिर एक foreach कुछ के लिए अधिक कुशल लग सकता है क्योंकि यह नोटेशन में छोटा है, लेकिन पृष्ठभूमि foreach में रीसेट, कुंजी और इसके लूपिंग करने के बगल में भी कॉल कहते हैं। लेकिन इसके अलावा यह अंत स्थिति की जांच के लिए भी वैध कॉल करता है, जो पूर्णांक जांच के संयोजन के कारण यहां से बचा जाता है।

याद रखें कि एक सरणी कुंजी केवल एक पूर्णांक या स्ट्रिंग हो सकती है, और सख्ती से संख्यात्मक स्ट्रिंग जैसे कि "1" (लेकिन "01") को पूर्णांक में अनुवादित नहीं किया जाएगा। यदि आप सरणी अनुक्रमिक होना चाहते हैं तो गिनती के अलावा एक पूर्णांक ऑपरेशन की जांच करने के लिए जो एक पूर्णांक कुंजी की जांच करता है। स्वाभाविक रूप से, अगर is_indexed_array झूठी रिटर्न देता है तो सरणी को सहयोगी के रूप में देखा जा सकता है। मैं 'देखा' कहता हूं, क्योंकि वास्तव में वे सभी हैं।


मैं जिस विधि का उपयोग करता हूं वह यहां है:

function is_associative ( $a )
{
    return in_array(false, array_map('is_numeric', array_keys($a)));
}

assert( true === is_associative(array(1, 2, 3, 4)) );

assert( false === is_associative(array('foo' => 'bar', 'bar' => 'baz')) );

assert( false === is_associative(array(1, 2, 3, 'foo' => 'bar')) );

ध्यान दें कि यह विशेष मामलों के लिए जिम्मेदार नहीं है जैसे:

$a = array( 1, 2, 3, 4 );

unset($a[1]);

assert( true === is_associative($a) );

क्षमा करें, आप इसके साथ मदद नहीं कर सकते हैं। यह निश्चित रूप से आकार के सरणी के लिए कुछ हद तक प्रदर्शन करता है, क्योंकि यह अनावश्यक प्रतिलिपि नहीं बनाता है। यह छोटी चीजें हैं जो पाइथन और रूबी को लिखने के लिए बहुत अच्छी बनाती हैं ...: पी


One way to approach this is to piggyback on json_encode , which already has its own internal method of differentiating between an associative array and an indexed array in order to output the correct JSON.

You can do this by checking to see if the first character returned after encoding is a { (associative array) or a [ (indexed array).

echo substr(json_encode($the_array), 0, 1) == '{' ? 'yes' : 'no';

मैंने array_keys($obj) !== range(0, count($obj) - 1) दोनों का उपयोग किया है array_keys($obj) !== range(0, count($obj) - 1) और array_values($arr) !== $arr (जो एक दूसरे के दोहरे हैं, हालांकि दूसरा सस्ता है पहला) लेकिन दोनों बहुत बड़े सरणी के लिए असफल हो जाते हैं।

ऐसा इसलिए है क्योंकि array_keys और array_values दोनों बहुत महंगा संचालन हैं (क्योंकि वे मूल रूप से मूल रूप से आकार की एक पूरी नई सरणी बनाते हैं)।

निम्नलिखित कार्य ऊपर दिए गए तरीकों की तुलना में अधिक मजबूत है:

function array_type( $obj ){
    $last_key = -1;
    $type = 'index';
    foreach( $obj as $key => $val ){
        if( !is_int( $key ) || $key < 0 ){
            return 'assoc';
        }
        if( $key !== $last_key + 1 ){
            $type = 'sparse';
        }
        $last_key = $key;
    }
    return $type;
}

यह भी ध्यान रखें कि यदि आप सहयोगी सरणी से स्पैर सरणी को अलग करने की परवाह नहीं करते हैं तो आप ब्लॉक के दोनों से 'assoc' वापस कर सकते हैं।

अंत में, जबकि यह इस पृष्ठ पर बहुत से "समाधान" की तुलना में बहुत कम "सुरुचिपूर्ण" प्रतीत हो सकता है, व्यावहारिक रूप से यह बहुत अधिक कुशल है। लगभग किसी भी सहयोगी सरणी का पता लगाया जाएगा। केवल अनुक्रमित सरणी पूरी तरह से जांच की जाएंगी, और ऊपर उल्लिखित विधियां न केवल अनुक्रमित सरणी को पूरी तरह से जांचेंगी, वे उन्हें डुप्लिकेट करेंगे।


Modification on the most popular answer.
This takes a little more processing, but is more accurate.

<?php
//$a is a subset of $b
function isSubset($a, $b)
{
    foreach($a =>$v)
        if(array_search($v, $b) === false)
            return false;

    return true;

    //less effecient, clearer implementation. (uses === for comparison)
    //return array_intersect($a, $b) === $a;
}

function isAssoc($arr)
{
    return !isSubset(array_keys($arr), range(0, count($arr) - 1));
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array(1 => 'a', 0 => 'b', 2 => 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false 
//(use === in isSubset to get 'true' for above statement)
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true
?>

I know it's a bit pointless adding an answer to this huge queue, but here's a readable O(n) solution that doesn't require duplicating any values:

function isNumericArray($array) {
    $count = count($array);
    for ($i = 0; $i < $count; $i++) {
        if (!isset($array[$i])) {
            return FALSE;
        }
    }
    return TRUE;
}

Rather than check the keys to see if they are all numeric, you iterate over the keys that would be there for a numeric array and make sure they exist.


function array_is_assoc(array $a) {
    $i = 0;
    foreach ($a as $k => $v) {
        if ($k !== $i++) {
            return true;
        }
    }
    return false;
}

तेज़, संक्षिप्त, और स्मृति कुशल। कोई महंगी तुलना, फ़ंक्शन कॉल या सरणी प्रतिलिपि नहीं।


<?php

function is_list($array) {
    return array_keys($array) === range(0, count($array) - 1);
}

function is_assoc($array) {
    return count(array_filter(array_keys($array), 'is_string')) == count($array);
}

?>

Both of these examples, which scored the most points do not work correctly with arrays like $array = array('foo' => 'bar', 1)


मेरा समाधान:

function isAssociative(array $array)
{
    return array_keys(array_merge($array)) !== range(0, count($array) - 1);
}

एक सरणी पर array_merge सभी integer कुंजी reindex होगा, लेकिन अन्य नहीं। उदाहरण के लिए:

array_merge([1 => 'One', 3 => 'Three', 'two' => 'Two', 6 => 'Six']);

// This will returns [0 => 'One', 1 => 'Three', 'two' => 'Two', 2 => 'Six']

तो यदि कोई सूची (एक गैर-सहयोगी सरणी) बनाई गई है ['a', 'b', 'c'] तो एक मान को unset($a[1]) हटा दिया जाता है, फिर array_merge कहा जाता है, सूची से पुन: संशोधित किया जाता है 0।


केवल यह जांचने के लिए कि सरणी में गैर-पूर्णांक कुंजी हैं (नहीं कि सरणी अनुक्रमिक रूप से अनुक्रमित या शून्य-अनुक्रमित है):

function has_string_keys(array $array) {
  return count(array_filter(array_keys($array), 'is_string')) > 0;
}

यदि कम से कम एक स्ट्रिंग कुंजी है, तो $array को एक सहयोगी सरणी के रूप में माना जाएगा।


स्पीड-वार:

function isAssoc($array)
{
    return ($array !== array_values($array));
}

मेमोरी के लिहाज से:

function isAssoc($array)
{
    $array = array_keys($array); return ($array !== array_keys($array));
}

जब तक कि PHP के लिए कोई अंतर्निहित न हो, आप ओ (एन) से कम में ऐसा करने में सक्षम नहीं होंगे - सभी चाबियों पर गणना करना और पूर्णांक प्रकार की जांच करना। वास्तव में, आप यह भी सुनिश्चित करना चाहते हैं कि कोई छेद नहीं है, इसलिए आपका एल्गोरिदम इस तरह दिख सकता है:

for i in 0 to len(your_array):
    if not defined(your-array[i]):
        # this is not an array array, it's an associative array :)

लेकिन परेशान क्यों? बस मान लें कि सरणी आपके द्वारा अपेक्षित प्रकार की है। यदि ऐसा नहीं है, तो यह आपके चेहरे पर उड़ाएगा - यह आपके लिए गतिशील प्रोग्रामिंग है! अपने कोड का परीक्षण करें और सब ठीक रहेगा ...


निश्चित रूप से यह एक बेहतर विकल्प है।

<?php
$arr = array(1,2,3,4);
$isIndexed = array_values($arr) === $arr;

ओपी द्वारा बताए गए अनुसार :

PHP सभी सरणी को सहयोगी के रूप में मानता है

यह एक ऐसा फ़ंक्शन लिखने के लिए काफी समझदार नहीं है (आईएमएचओ) जो जांचता है कि कोई सरणी सहयोगी है या नहीं । तो सबसे पहले सबसे पहले: PHP सरणी में एक कुंजी क्या है?:

कुंजी या तो एक पूर्णांक या एक स्ट्रिंग हो सकता है

इसका मतलब है कि 3 संभावित मामले हैं:

  • प्रकरण 1. सभी चाबियाँ संख्यात्मक / पूर्णांक हैं
  • मामला 2. सभी चाबियाँ तार हैं
  • केस 3. कुछ चाबियाँ तार हैं , कुछ चाबियाँ संख्यात्मक / पूर्णांक हैं

हम निम्नलिखित कार्यों के साथ प्रत्येक मामले की जांच कर सकते हैं।

प्रकरण 1: सभी कुंजी संख्यात्मक / पूर्णांक हैं

नोट : यह फ़ंक्शन खाली सरणी के लिए भी सच है।

//! Check whether the input is an array whose keys are all integers.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all integers.
*/
function IsArrayAllKeyInt($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}

प्रकरण 2: सभी चाबियाँ तार हैं

नोट : यह फ़ंक्शन खाली सरणी के लिए भी सच है।

//! Check whether the input is an array whose keys are all strings.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all strings.
*/
function IsArrayAllKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_string", array_keys($InputArray))) === array(true);
}

केस 3. कुछ चाबियाँ तार हैं , कुछ चाबियाँ संख्यात्मक / पूर्णांक हैं

नोट : यह फ़ंक्शन खाली सरणी के लिए भी सच है।

//! Check whether the input is an array with at least one key being an integer and at least one key being a string.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array with at least one key being an integer and at least one key being a string.
*/
function IsArraySomeKeyIntAndSomeKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return count(array_unique(array_map("is_string", array_keys($InputArray)))) >= 2;
}

यह इस प्रकार है कि:

अब, एक सरणी के लिए एक "असली" सरणी है जिसे हम सभी के आदी हैं, जिसका अर्थ है:

  • इसकी चाबियाँ सभी संख्यात्मक / पूर्णांक हैं
  • इसकी चाबियाँ अनुक्रमिक हैं (यानी चरण 1 से बढ़ रही है)।
  • इसकी चाबियाँ शून्य से शुरू होती हैं

हम निम्नलिखित फ़ंक्शन से जांच सकते हैं।

केस 3 ए। कुंजी संख्यात्मक / पूर्णांक , क्रमिक , और शून्य-आधारित हैं

नोट : यह फ़ंक्शन खाली सरणी के लिए भी सच है।

//! Check whether the input is an array whose keys are numeric, sequential, and zero-based.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are numeric, sequential, and zero-based.
*/
function IsArrayKeyNumericSequentialZeroBased($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_keys($InputArray) === range(0, count($InputArray) - 1);
}

चेतावनी / Pitfalls (या, PHP में सरणी कुंजी के बारे में और भी असाधारण तथ्यों)

इंटीजर कुंजी

इन सरणी के लिए कुंजी integers :

array(0 => "b");
array(13 => "b");
array(-13 => "b");          // Negative integers are also integers.
array(0x1A => "b");         // Hexadecimal notation.

स्ट्रिंग कुंजी

इन सरणी के लिए कुंजी strings :

array("fish and chips" => "b");
array("" => "b");                                   // An empty string is also a string.
array("[email protected]" => "b");    // Strings may contain non-alphanumeric characters.
array("stack\t\"over\"\r\nflow's cool" => "b");     // Strings may contain special characters.
array('$tα€k↔øv∈rflöw⛄' => "b");                    // Strings may contain all kinds of symbols.
array("functіon" => "b");                           // You think this looks fine? Think again! (see https://.com/q/9246051/1402846)
array("ま말轉转ДŁ" => "b");                         // How about Japanese/Korean/Chinese/Russian/Polish?
array("fi\x0sh" => "b");                            // Strings may contain null characters.
array(file_get_contents("https://www.google.com/images/nav_logo114.png") => "b");   // Strings may even be binary!

स्ट्रिंग की तरह दिखने वाली इंटीजर कुंजी

यदि आपको लगता है कि array("13" => "b") में कुंजी array("13" => "b") एक स्ट्रिंग है , तो आप गलत हैंयहां दस्तावेज़ से:

वैध पूर्णांक वाले स्ट्रिंग को पूर्णांक प्रकार में डाला जाएगा। जैसे कुंजी "8" वास्तव में 8 के तहत संग्रहीत किया जाएगा। दूसरी तरफ "08" नहीं डाला जाएगा, क्योंकि यह वैध दशमलव पूर्णांक नहीं है।

उदाहरण के लिए, इन सरणी के लिए कुंजी पूर्णांक हैं :

array("13" => "b");
array("-13" => "b");                        // Negative, ok.

लेकिन इन सरणी के लिए कुंजी तार हैं :

array("13." => "b");
array("+13" => "b");                        // Positive, not ok.
array("-013" => "b");
array("0x1A" => "b");                       // Not converted to integers even though it's a valid hexadecimal number.
array("013" => "b");                        // Not converted to integers even though it's a valid octal number.
array("18446744073709551616" => "b");       // Not converted to integers as it can't fit into a 64-bit integer.

doc मुताबिक, और क्या है,

एक पूर्णांक का आकार प्लेटफॉर्म-निर्भर है, हालांकि लगभग दो बिलियन का अधिकतम मूल्य सामान्य मान है (यह 32 बिट्स पर हस्ताक्षर किए गए हैं)। 64-बिट प्लेटफार्मों में आमतौर पर लगभग 9ई 18 का अधिकतम मूल्य होता है, विंडोज के अलावा, जो हमेशा 32 बिट होता है। PHP हस्ताक्षरित पूर्णांक का समर्थन नहीं करता है।

तो इस सरणी की कुंजी एक पूर्णांक हो सकती है या नहीं भी हो सकती है - यह आपके प्लेटफ़ॉर्म पर निर्भर करती है।

array("60000000000" => "b");                // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.

इससे भी बदतर, PHP पूर्णांक 2 31 = 2,147,483,648 सीमा के करीब है (देखें 51430 , बग 528 99 देखें )। उदाहरण के लिए, मेरे स्थानीय वातावरण पर (विंडोज 7 पर एक्सएएमपीपी 1.7.7 पर PHP 5.3.8), var_dump(array("2147483647" => "b")) देता है

array(1) {
    [2147483647]=>
    string(1) "b"
}   

लेकिन कोडेपैड (PHP 5.2.5) पर इस लाइव डेमो पर , वही अभिव्यक्ति देता है

array(1) {
    ["2147483647"]=>
    string(1) "b"
}

तो कुंजी एक पर्यावरण में एक पूर्णांक है लेकिन दूसरे में एक स्ट्रिंग है, भले ही 2147483647 मान्य हस्ताक्षरित 32-बिट पूर्णांक है


Could this be the solution?

  public static function isArrayAssociative(array $array) {
      reset($array);
      return !is_int(key($array));
  }

The caveat is obviously that the array cursor is reset but I'd say probably the function is used before the array is even traversed or used.


function is_array_assoc($foo) {
    if (is_array($foo)) {
        return (count(array_filter(array_keys($foo), 'is_string')) > 0);
    }
    return false;
}

I think the definition of a scalar array will vary by application. That is, some applications will require a more strict sense of what qualifies as a scalar array, and some applications will require a more loose sense.

Below I present 3 methods of varying strictness.

<?php
/**
 * Since PHP stores all arrays as associative internally, there is no proper
 * definition of a scalar array.
 * 
 * As such, developers are likely to have varying definitions of scalar array,
 * based on their application needs.
 * 
 * In this file, I present 3 increasingly strict methods of determining if an
 * array is scalar.
 * 
 * @author David Farrell <[email protected]>
 */

/**
 * isArrayWithOnlyIntKeys defines a scalar array as containing
 * only integer keys.
 * 
 * If you are explicitly setting integer keys on an array, you
 * may need this function to determine scalar-ness.
 * 
 * @param array $a
 * @return boolean
 */ 
function isArrayWithOnlyIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    foreach ($a as $k => $v)
        if (!is_int($k))
            return false;
    return true;
}

/**
 * isArrayWithOnlyAscendingIntKeys defines a scalar array as
 * containing only integer keys in ascending (but not necessarily
 * sequential) order.
 * 
 * If you are performing pushes, pops, and unsets on your array,
 * you may need this function to determine scalar-ness.
 * 
 * @param array $a
 * @return boolean
 */ 
function isArrayWithOnlyAscendingIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    $prev = null;
    foreach ($a as $k => $v)
    {
        if (!is_int($k) || (null !== $prev && $k <= $prev))
            return false;
        $prev = $k;
    }
    return true;
}

/**
 * isArrayWithOnlyZeroBasedSequentialIntKeys defines a scalar array
 * as containing only integer keys in sequential, ascending order,
 * starting from 0.
 * 
 * If you are only performing operations on your array that are
 * guaranteed to either maintain consistent key values, or that
 * re-base the keys for consistency, then you can use this function.
 * 
 * @param array $a
 * @return boolean
 */
function isArrayWithOnlyZeroBasedSequentialIntKeys(array $a)
{
    if (!is_array($a))
        return false;
    $i = 0;
    foreach ($a as $k => $v)
        if ($i++ !== $k)
            return false;
    return true;
}

I compare the difference between the keys of the array and the keys of the result of array_values() of the array, which will always be an array with integer indices. If the keys are the same, it's not an associative array.

function isHash($array) {
    if (!is_array($array)) return false;
    $diff = array_diff_assoc($array, array_values($array));
    return (empty($diff)) ? false : true;
}

वास्तव में सबसे प्रभावी तरीका इस प्रकार है:

function is_assoc($array){
   $keys = array_keys($array);
   return $keys !== array_keys($keys);
}

यह काम करता है क्योंकि यह चाबियों की कुंजी (जो अनुक्रमिक सरणी के लिए हमेशा 0,1,2 आदि) कुंजी की चाबियों से तुलना करता है (जो हमेशा 0,1,2 आदि होगा)।


मैंने इस प्रश्न के लिए दो लोकप्रिय दृष्टिकोण देखा: एक array_values() और अन्य का उपयोग key() का उपयोग कर। यह पता लगाने के लिए कि कौन सा तेज़ है, मैंने एक छोटा कार्यक्रम लिखा:

$arrays = Array(
  'Array #1' => Array(1, 2, 3, 54, 23, 212, 123, 1, 1),
  'Array #2' => Array("Stack", 1.5, 20, Array(3.4)),
  'Array #3' => Array(1 => 4, 2 => 2),
  'Array #4' => Array(3.0, "2", 3000, "Stack", 5 => "4"),
  'Array #5' => Array("3" => 4, "2" => 2),
  'Array #6' => Array("0" => "One", 1.0 => "Two", 2 => "Three"),
  'Array #7' => Array(3 => "asdf", 4 => "asdf"),
  'Array #8' => Array("apple" => 1, "orange" => 2),
);

function is_indexed_array_1(Array &$arr) {
  return $arr === array_values($arr);
}

function is_indexed_array_2(Array &$arr) {
  for (reset($arr), $i = 0; key($arr) === $i++; next($arr))
    ;
  return is_null(key($arr));
}

// Method #1
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
  foreach ($arrays as $array) {
    $dummy = is_indexed_array_1($array);
  }
}
$end = microtime(true);
echo "Time taken with method #1 = ".round(($end-$start)*1000.0,3)."ms\n";

// Method #2
$start = microtime(true);
for ($i = 0; $i < 1000; $i++) {
  foreach ($arrays as $array) {
    $dummy = is_indexed_array_2($array);
  }
}
$end = microtime(true);
echo "Time taken with method #1 = ".round(($end-$start)*1000.0,3)."ms\n";

CentOS पर PHP 5.2 पर प्रोग्राम के लिए आउटपुट निम्नानुसार है:

विधि # 1 = 10.745ms के साथ लिया गया समय
विधि # 2 = 18.239ms के साथ लिया गया समय

PHP 5.3 पर आउटपुट ने इसी तरह के परिणाम दिए। स्पष्ट रूप से array_values() का उपयोग करना बहुत तेज़ है।





arrays