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


781

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

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

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

और इस:

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

382
आपके कोड में एक बग है: टमाटर एक फल है।
ओलले हर्स्टेड्ट

9
इस विधि में कैवियट हैं, लेकिन अक्सर मैं बस करता हूं if (isset($array[0])), जो सरल और तेज है। बेशक, आपको पहले यह सुनिश्चित करना चाहिए कि सरणी खाली नहीं है, और आपको सरणी के संभावित सामग्रियों पर कुछ ज्ञान होना चाहिए ताकि विधि विफल न हो (जैसे मिश्रित संख्यात्मक / साहचर्य, या गैर-अनुक्रमिक)।
ग्रास डबल

अमेरिका के उच्च न्यायालय के अनुसार @ ओलेहर्स्टेड्ट नहीं । ;-)
एमसी सम्राट

जवाबों:


622

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

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

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

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

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

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

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

32
बहुत ही सुंदर समाधान। ध्यान दें कि यह खाली सरणी के मामले में (अस्पष्ट) मामले में TRUE लौटाता है।
जोनाथन लिडबेक

30
मुझे लगता है कि साहचर्य सरणियों के विशेष मामले के रूप में अनुक्रमिक सरणियों के बारे में सोचना अधिक उपयोगी है। इसलिए प्रत्येक सरणी साहचर्य है, लेकिन केवल कुछ अनुक्रमिक हैं। इसलिए, एक फ़ंक्शन की isSequential()तुलना में अधिक समझ में आता है isAssoc()। ऐसे फ़ंक्शन में, खाली सरणी को अनुक्रमिक के रूप में देखा जाना चाहिए। सूत्र हो सकता है array() === $arr || !isAssoc($arr)
दान

18
मुझे लगता है कि यह बहुत सारे संभावित सीपीयू समय और मेमोरी से बचता है अगर कोई जांच करेगा कि क्यासेट ($ गिरफ्तारी [0]) सभी कुंजियों को निकालने से पहले गलत है, क्योंकि यह स्पष्ट रूप से साहचर्य है यदि सरणी खाली नहीं है, लेकिन 0 में कोई तत्व नहीं है। स्थान। जैसा कि "सबसे" वास्तविक साहचर्य सरणियों में कुंजी के रूप में तार होते हैं यह इस तरह के फ़ंक्शन के सामान्य मामले के लिए एक अच्छा अनुकूलन होना चाहिए।
ओडरवेट

10
@OderWat - यदि आपका शून्य तत्व शून्य मान है, तो array_key_existsइसके बजाय आपके ऑप्टिमाइज़ेशन का उपयोग करना चाहिए, गलत शुरुआत issetगलत तरीके से वापस आ जाएगी। एक अशक्त मान आमतौर पर इस तरह के एक सरणी में एक वैध मूल्य होना चाहिए।
OCDev

@MAChitgarha, आपके संपादन ने बिना किसी स्पष्टीकरण के फ़ंक्शन के व्यवहार को बदल दिया, और इसे गद्य में वर्णन से उलट कर दिया कि यह वास्तव में क्या करने वाला है। मैंने इसे वापस कर दिया है।
मार्क अमेरी

431

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

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

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


22
यह तरीका जितना लगता है उससे कहीं ज्यादा बेहतर है। यदि काउंट (फ़िल्टर्ड_अरे) == काउंट (ओरिजिनल_अरे) किया जाता है, तो यह एक एशो एरे है। यदि गिनती (फ़िल्टर की गई) == 0 है, तो यह अनुक्रमित सरणी है। यदि गणना (फ़िल्टर्ड_अरे) <गणना (ओरिजिनल_अरे) की जाती है, तो सरणी में संख्यात्मक और स्ट्रिंग दोनों कुंजियाँ हैं।
जामोल

5
@MikePretzlaw बेशक यह पुनरावृति करता है; वहाँ (जाहिर है) यह निर्धारित करने का कोई संभावित तरीका नहीं है कि सरणी के सभी कुंजियों को देखे बिना सरणी के सभी कुंजी हैं या नहीं। मुझे लगता है कि गैर-चलने वाले विकल्प हम नीचे देख रहे हैं, जैसे हैं $isIndexed = array_values($arr) === $arr;? जिस पर मैं पूछता हूं: आपको क्या लगता है कि कैसे array_values()काम करता है? आपको क्या लगता ===है कि सरणियों के कार्यों के लिए आवेदन कैसे किया जाता है? जवाब यह है कि वे भी सरणी पर पुनरावृति करते हैं।
मार्क अमेरी

4
@AR "अगर यह हो सकता है, तो PHP एक सरणी परिभाषा में एक उदाहरण के लिए सबकुछ डालने का प्रतीत होता है। - हाँ, बिल्कुल ऐसा ही होता है। सबसे बड़ी डब्ल्यूटीएफ यह है कि यह तैरने के लिए भी ऐसा करता है; यदि आप कोशिश करते हैं var_dump([1.2 => 'foo', 1.5 => 'bar']);तो आपको पता चलेगा कि आपको सरणी मिलती है [1 => 'bar']। कोई तरीका नहीं है कि किसी कुंजी के मूल प्रकार का पता लगाएं। हाँ, यह सब भयानक है; PHP की सरणियाँ भाषा का अब तक का सबसे खराब हिस्सा हैं, और अधिकांश क्षति अपूरणीय हैं और पारंपरिक सरणियों और पारंपरिक हैशमैप के लिए शुरुआत से ही एक भयानक निर्माण का उपयोग करने के विचार के कारण हैं।
मार्क एमी

30
@MarkAmery ऊपर, जबकि सरल, सरणी के 100% चलने की गारंटी देता है। यह अधिक कुशल होगा, खासकर यदि आप बड़े सरणियों के साथ काम कर रहे हैं, यदि आप स्ट्रिंग या इंट के लिए जाँच कर रहे थे और पहले मिले पर टूट गए। उदाहरण के लिए: function isAssociative($arr) { foreach ($arr as $key => $value) { if (is_string($key)) return true; } return false; }
सोचा

1
@ आपका कोड बहुत तेज़ी से काम करता है, लेकिन यह अनुक्रमिक सरणी का पता नहीं लगा सकता है । उदाहरण array(1 => 'a', 0 => 'b', 2 => 'c')बन जाएगा false(अनुक्रमिक सरणी) जबकि यह होना चाहिए true(साहचर्य सरणी)। toolsqa.com/data-structures/array-in-programming मुझे यकीन नहीं है कि कुंजी आरोही क्रम होनी चाहिए? (0, 1, ...)
वी

132

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

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

52
यह एरे में मूल्यों की नकल करेगा, जो संभावित रूप से बहुत महंगा है। आप सरणी कुंजियों की जांच कर रहे हैं।
meagar

8
मैंने अभी == प्रयोग किया; मुझे नहीं लगता कि यहां === की आवश्यकता है। लेकिन "परेशान करने के लिए और यह काम नहीं करता है" का जवाब देने के लिए: एक बार जब आप पहले तत्व को परेशान करते हैं, तो यह अब पूर्णांक-अनुक्रमित सरणी नहीं है जो 0. पर शुरू होता है। तो IMO यह काम करता है।
अनुदान

4
@Grantwparks से सहमत: एक विरल सरणी अनुक्रमित नहीं है। दिलचस्प बात यह है कि वास्तव में अनुक्रमित सरणी PHP के बीच से एक तत्व को हटाने का कोई तरीका नहीं है, मूल रूप से सभी सरणियों को साहचर्य और संख्यात्मक के रूप में घोषित कर रहा है, बस एक 'मेरे लिए कुंजी बना' संस्करण है।
रिकमशाम

7
मेरे पास एकमात्र समस्या यह है कि ===मानों के बराबर होने पर भी समय की जाँच करना बेकार हो जाएगा, भले ही हम केवल कुंजियों में रुचि रखते हों। इस कारण से मैं $k = array_keys( $arr ); return $k === array_keys( $k );संस्करण को पसंद करता हूं ।
जेसी

5
एक जोड़ा गया नोट, यह संख्यात्मक कुंजियों के साथ निर्दिष्ट सरणियों पर विफल होता है जो क्रम से बाहर हैं। जैसे $ myArr = array (0 => 'a', 3 => 'b', 4 => 1, 2 => 2, 1 => '3'); टेस्ट करने से पहले एक संभावित काम ksort ($ arr) चल रहा है
Scott

77

इस सवाल में कई टिप्पणीकारों को समझ में नहीं आता है कि PHP में सरणियाँ कैसे काम करती हैं। से सरणी प्रलेखन :

एक कुंजी एक पूर्णांक या एक स्ट्रिंग हो सकती है। यदि एक कुंजी पूर्णांक का मानक प्रतिनिधित्व है, तो इसे इस तरह से व्याख्या किया जाएगा (अर्थात "8" की व्याख्या 8 के रूप में की जाएगी, जबकि "08" की व्याख्या "08" के रूप में की जाएगी। कुंजी में फ़्लोट्स को पूर्णांक में काट दिया जाता है। अनुक्रमित और साहचर्य सरणी प्रकार PHP में एक ही प्रकार हैं, जिसमें पूर्णांक और स्ट्रिंग सूचक दोनों हो सकते हैं।

दूसरे शब्दों में, "8" की एक सरणी कुंजी के रूप में ऐसी कोई चीज नहीं है क्योंकि यह हमेशा (चुपचाप) पूर्णांक में परिवर्तित हो जाएगी। 8. इसलिए पूर्णांक और संख्यात्मक तार के बीच अंतर करने की कोशिश अनावश्यक है।

यदि आप सरणी के भाग (जैसे कि array_keys () करता है) या इसके सभी भाग (जैसे कि foreach does) की प्रतिलिपि बनाए बिना गैर-पूर्णांक कुंजियों के लिए किसी सरणी की जाँच करने के लिए सबसे कुशल तरीका चाहते हैं:

function keyedNext( &$arr, &$k){
    $k = key($arr);
    return next($arr);
}

for ($k = key(reset($my_array)); is_int($k); keyedNext($my_array,$k))
    $onlyIntKeys = is_null($k);

यह काम करता है क्योंकि कुंजी () वर्तमान सरणी स्थिति अमान्य होने पर NULL लौटाती है और NULL कभी भी एक वैध कुंजी नहीं हो सकती है (यदि आप NULL को एक सरणी कुंजी के रूप में उपयोग करने का प्रयास करते हैं तो यह चुपचाप "" में परिवर्तित हो जाती है)।


यह गैर-अनुक्रमिक पूर्णांक कुंजियों के लिए काम नहीं करता है। इसे [2 => 'a', 4 => 'b'] के साथ आज़माएँ।
डेविड जेएपी

2
@ डेविड, आपको "काम नहीं करता" से क्या मतलब है? यह सफलतापूर्वक निर्धारित करता है कि सभी कुंजी पूर्णांक हैं। क्या आप दावा कर रहे हैं कि आपके द्वारा पोस्ट की गई एक सरणी को "संख्यात्मक सरणी" नहीं माना जाना चाहिए?
coredumperror

7
एक गैर साहचर्य सरणी से लेकर कुंजी होना आवश्यक है 0करने के लिए count($array)-1इस सख्त आदेश में,। प्रारंभिक जांच से is_array()मदद मिल सकती है। कुंजी अनुक्रम की जाँच करने के लिए एक बढ़ता हुआ चर जोड़ें: for ($k = 0, reset($array) ; $k === key($array) ; next($array)) ++$k;जो सौदा तय करता है।
आवारे

2
foreachस्पष्ट पुनरावृत्ति के बजाय का उपयोग करना लगभग दो बार तेज है।
आव्रे

1
यदि आप इसे एक समारोह में बनाना चाहते हैं: function isAssocStr($array) { for (reset($array); is_int(key($array)); next($array)) { if (is_null(key($array))) return false; } return true; }
GreeKrrina

39

जैसा कि ओपी ने कहा है :

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

यह एक फ़ंक्शन लिखने के लिए काफी समझदार (IMHO) नहीं है जो यह जांचता है कि क्या कोई सरणी साहचर्य है । तो पहली बात पहली: एक 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);
}

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

पूर्णांक कुंजी

इन सरणियों की कुंजी पूर्णांक हैं :

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

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

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

array("fish and chips" => "b");
array("" => "b");                                   // An empty string is also a string.
array("stackoverflow_email@example.com" => "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://stackoverflow.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")एक स्ट्रिंग है , तो आप गलत हैंयहाँ डॉक्टर से :

मान्य पूर्णांक वाले स्ट्रिंग्स को पूर्णांक प्रकार में डाला जाएगा। उदाहरण के लिए "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.

क्या, और भी है के अनुसार दस्तावेज़ ,

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

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

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

इससे भी बदतर, अगर पूर्णांक 2 31 = 2,147,483,648 सीमा ( बग 51430 , बग 52899 देखें ) के पास है , तो PHP छोटी गाड़ी होती है । उदाहरण के लिए, मेरे स्थानीय वातावरण पर (विंडोज 7 पर XAMPP 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-बिट पूर्णांक है


2
सिवाय, जैसा कि मैंने नीचे उल्लेख किया है, इसमें एक डुप्लिकेट सरणी बनाने की जाँच की जा रही है, जिससे यह बड़े सरणियों के लिए बहुत महंगा है, और साझा मेजबानों पर मेमोरी क्रैश से बाहर निकलने का एक संभावित स्रोत है।
पॉडपर्सन

35

स्पीड-वार:

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

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

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

निम्नलिखित सरणी: सरणी (02 => 11,1,2,456); उपरोक्त एल्गोरिथ्म का उपयोग करते हुए संख्यात्मक कुंजियाँ नहीं होने के रूप में दिखाया गया है, भले ही 02 === 2
गैलीलियो_गैलिइ

20
function checkAssoc($array){
    return  ctype_digit( implode('', array_keys($array) ) );
}

2
यह एकमात्र उत्तर है (मेरी टिप्पणी के समय) जो निम्नलिखित से निपट सकता है: $ array = array (0 => 'blah', 2 => 'yep', 3 => 'wahey')
Shabbyrobe

लेकिन array('1'=>'asdf', '2'=>'too')साहचर्य सरणी के रूप में माना जाएगा जबकि यह वास्तव में नहीं है (चाबियाँ वास्तव में स्ट्रिंग हैं)
कैप्टन कुरो

1
@ कैप्टेनकुरो का मतलब है आप संख्यात्मक। यह एक सहयोगी सरणी है।
devios1

1
trueयदि फ़ंक्शन निम्न हैं, तो कुंजियाँ: शून्य, पूर्णांक (केवल धनात्मक), एक रिक्त स्ट्रिंग, या उपरोक्त कोई भी संयोजन, जैसे कि स्ट्रिंग "09"। यह फ़ंक्शन कुंजियों के क्रम को ध्यान में नहीं रखता है। तो array(0=>'blah', 2=>'yep', 3=>'wahey'), array(0=>'blah', 2=>'yep', 1=>'wahey')और array('blah', 'yep', 'wahey')इस समारोह के अनुसार सभी सहयोगी हैं, जबकि array('a'=>'blah', 'b'=>'yep', 'c'=>'wahey')ऐसा नहीं है।
पैंग

@CaptainkurO आप गलत हैं। '1' और '2' को पूर्णांक के रूप में संग्रहीत किया जाएगा। गिलहरी के उत्तर का उद्धृत भाग 11 मई, 2011 को 19:34 पर पढ़ें। PHP स्ट्रिंग कुंजियों को संग्रहीत नहीं करता है जो बिल्कुल पूर्णांक की तरह दिखते हैं। यह उन पूर्णांकों को धर्मान्तरित करता है।
बुटेल बटुकस

20

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

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

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


1
चतुर, लेकिन अच्छा नहीं। यह "सबसे कुशल" क्यों है? यह सिर्फ सरणी_की ($ a) से लेकर रेंज (0, काउंट ($ a)) तक तुलना करने के लिए बहुत अधिक पठनीय होगा। सबसे चतुर समाधान शायद ही कभी मेरे अनुभव में सबसे अच्छा है। खासकर जब चतुर होने का शाब्दिक रूप से स्पष्ट और स्वच्छ विकल्प पर कोई मूल्य नहीं होता है।
शेन एच।

4
यह फ़ंक्शन true, array(1=>"a")लेकिन इसके falseलिए लौटता है array("a"=>"a")!=द्वारा प्रतिस्थापित किया जाता है तो अधिक सार्थक होगा !==
पैंग

1
@ आप सही हैं। मुझे लगा कि आपकी टिप्पणी निश्चित रूप से पहले गलत होनी चाहिए, लेकिन, मेरे आश्चर्य के लिए, [0] == ['a']PHP में (क्योंकि 0 == 'a', और वास्तव में, 0 == 'banana')। PHP का ==ऑपरेटर पागल है।
मार्क अमेरी

2
यह कुशल इन्सोफ़र नहीं है क्योंकि इसमें सरणी_कील्स को कॉल करना शामिल है। जब तक आप एक गैर-अनुक्रमिक पूर्णांक इंडेक्स नहीं पाते हैं। हुड के तहत आप वैसे भी कर रहे हैं , लेकिन आपने पहले से ही एक बड़े सरणी की नकल की है।
पॉडपर्सन

17

मैंने दोनों का उपयोग किया है 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'दोनों ifब्लॉकों से वापस आ सकते हैं।

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


13

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

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 करना कम (कम कोड) लग सकता है, लेकिन ध्यान रखें कि एक बार कॉल करने के बाद बैकग्राउंड में क्या होता है। हाँ, कुछ अन्य समाधानों की तुलना में अधिक (दृश्यमान) कथन हैं, लेकिन यह वह नहीं है जो मायने रखता है?
  • समय के अनुसार: इस तथ्य के अलावा कि डेटा और / या कुंजियों की प्रतिलिपि बनाने / निकालने में भी समय लगता है, यह समाधान फ़ॉरच करने से अधिक कुशल है। फिर से कुछ के लिए अधिक कुशल लग सकता है क्योंकि यह संकेतन में छोटा है, लेकिन पृष्ठभूमि में फॉरेक्स रीसेट, कुंजी और इसके बाद लूपिंग करने के लिए कहता है। लेकिन इसके अलावा यह अंतिम स्थिति की जांच करने के लिए वैध भी है, जो पूर्णांक जांच के साथ संयोजन के कारण यहां से बचा जाता है।

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


1
यह सबसे अच्छा जवाब है। "साहचर्य" या "संख्यात्मक" सरणी की परिभाषा विशिष्ट स्थिति पर निर्भर करती है।
पाटो

यदि फ़ॉरच का उपयोग यहां की विधि से कम कुशल है, तो दो अलग-अलग कार्यों का उपयोग करने की असुविधा से अलग, इस समाधान का प्रदर्शन मेरा (पूर्ववर्ती) की तुलना में बेहतर है। मुझे संदेह है कि यह नहीं है, क्योंकि एक सरणी के माध्यम से जाने के लिए सबसे तेज़ तरीके के रूप में फॉर्चेक की सिफारिश की जाती है।
पॉडपर्सन

7

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

  • सूचकांक में छेद के साथ सरणी (जैसे 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;
}

1
"यदि चाबियों में से एक पूर्णांक नहीं है, तो यह साहचर्य सरणी है, अन्यथा यह अनुक्रमिक है" - हुह? नहीं, यह केवल गलत है। "साहचर्य" सरणी का गठन करने के तर्क के लिए जगह है, लेकिन "अनुक्रमिक" का अर्थ बहुत अस्पष्ट है, और यह सभी कुंजियों की संख्या के समान नहीं है।
मार्क अमेरी

यदि चाबियों में से एक पूर्णांक नहीं है, तो यह स्वभाव से IS साहचर्य है, हालांकि, यह केवल अनुक्रमिक है यदि कुंजियां 0 - लंबाई (सरणी) से जाती हैं - 1. यह NUMERIC हालांकि, यदि सभी कुंजियां केवल गिने जा रही हैं, लेकिन हो सकता है या कई सरणी फ़ंक्शंस के साथ काम नहीं कर सकते हैं जिन्हें अनुक्रमिक सरणी की आवश्यकता होती है। यदि आप उस पर array_values ​​(सरणी) चलाकर संख्यात्मक सरणी को छेद के साथ अनुक्रमिक में परिवर्तित करते हैं, तो इसे अनुक्रमिक में बदल दिया जाएगा।
भू

7

मैंने इस प्रश्न के लिए दो लोकप्रिय दृष्टिकोणों पर ध्यान दिया: एक का उपयोग करना 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()ज्यादा तेज है।


खराब बेंचमार्क। आपने बड़े सरणियों के लिए परीक्षण नहीं किया। मेरे कंप्यूटर पर 10K + एलिमेंट्स मेथड # 2 से शुरू होता है। $arrays = Array( 'Array #1' => range(0, 50000), );
बकवास

7

इस से संपर्क करने का एक तरीका पिगीबैक पर है json_encode, जिसमें पहले से ही सही JSON आउटपुट के लिए एक साहचर्य सरणी और अनुक्रमित सरणी के बीच अंतर करने की अपनी आंतरिक विधि है।

आप यह देखने के लिए जाँच कर सकते हैं कि एन्कोडिंग के बाद लौटा पहला वर्ण एक {(साहचर्य सरणी) है या [(अनुक्रमित सरणी)।

// Too short :)
function is_assoc($arr) {
    ksort($arr);
    return json_encode($arr)[0] === '{';
}

मेरी राय में ksort () आवश्यक नहीं है। यह समाधान काम कर रहा है, लेकिन यह परीक्षण करना है कि क्या $ गिरफ्तारी शून्य है और यदि json_encode विफल रहता है, तो एक कोशिश / पकड़। + यह वास्तव में इष्टतम नहीं है यदि $ गिरफ्तारी बड़ी है।
लूसबोनिन

7

कई उत्तर पहले से ही हैं, लेकिन यहाँ वह विधि है जो लारवेल अपने अर्र वर्ग के भीतर निर्भर करती है:

/**
 * Determines if an array is associative.
 *
 * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
 *
 * @param  array  $array
 * @return bool
 */
public static function isAssoc(array $array)
{
    $keys = array_keys($array);

    return array_keys($keys) !== $keys;
}

स्रोत: https://github.com/laravel/framework/blob/5.4/src/Illuminate/Support/Arr.php


1
@ कैसी array_keys($keys)संख्या का एक क्रमिक सरणी लौटाएगा (0 ... X) जिसकी मूल सरणी की लंबाई समान है। उदाहरण के लिए array_keys(["a", "b", "c"]) = [0, 1, 2]; array_keys([0, 1, 2]) = [0, 1, 2](यह एक अनुक्रमिक सरणी है क्योंकि [0, 1, 2] !== [0, 1, 2])। एक और उदाहरण: array_keys(["a" => 5, "b" => 7, "c" => 10]) = ["a", "b", "c"]; array_keys(["a", "b", "c"]) = [0, 1, 2](यह एक साहचर्य सरणी है क्योंकि ["a", "b", "c"] !== [0, 1, 2])। आशा है कि यह स्पष्ट है (एक टिप्पणी में बड़े पैमाने पर व्याख्या करने के लिए मुश्किल है, कम से कम मेरे लिए)
वेलेपू

यह एल्गोरिथ्म पागल, आसान, समझने योग्य है।
बेनी

यदि आपके पास सहयोगी पंक्तियों का अनुक्रमिक सरणी है तो यह काम नहीं करेगा।
लक्सबोनिन

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

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


4

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

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

if (array_is_indexed($array)) {  }

या:

if (array_is_assoc($array)) {  }

3

मुझे पता है कि इस विशाल कतार में उत्तर जोड़ना थोड़ा व्यर्थ है, लेकिन यहाँ एक पठनीय O (n) समाधान है जिसे किसी भी मान को डुप्लिकेट करने की आवश्यकता नहीं है:

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

कुंजी की जाँच करने के बजाय आप पुनरावृति कुंजी उस पर अगर वे सब सांख्यिक को देखने के लिए, होगा एक संख्यात्मक सरणी के लिए वहाँ हो और सुनिश्चित करें कि वे मौजूद हैं।


एक और बात। फार्म में सरणी [1,2,null,4]विफल हो जाएगी, लेकिन यह सही सरणी है। इसलिए मैंने जोड़array_key_exists
तोड़ के

-1; isset()यहाँ गलत उपकरण है क्योंकि यह गलत है अगर मान सेट है null, लेकिन @lazycommit द्वारा बताया गया है।
मार्क अमेरी

3

मेरा समाधान:

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

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

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 से शुरू होती है।


-1; यह O(n)अतिरिक्त मेमोरी में उपयोग किया जाता है (क्योंकि यह कई तत्वों के साथ कई नए सरणियों का निर्माण करता है $array), उत्तर उस प्रश्न की अस्पष्टता को संबोधित नहीं करता है जो पूछा गया था और न ही यह स्पष्ट करता है कि यह कैसे सूची / गैर-सहयोगी सरणी को परिभाषित कर रहा है, और यहां तक ​​कि यदि इनमें से कोई भी बिंदु सत्य नहीं था, तो यह स्पष्ट नहीं है कि यह पहले से ही पोस्ट किए गए अन्य उत्तरों की तुलना में कोई भी मूल्य जोड़ता है।
मार्क अमेरी

3

कुछ स्थानीय बेंचमार्किंग, डिबगिंग, कंपाइलर प्रोबिंग, प्रोफाइलिंग, और 3v4l.org को अधिक संस्करणों में बेंचमार्क करने के लिए दुरुपयोग करने के बाद (हां, मुझे रुकने की चेतावनी मिली) और हर बदलाव के खिलाफ तुलना जो मुझे मिल सकती है ...

मैं आपको एक संगठित रूप से प्राप्त सबसे अच्छा-औसत-सबसे खराब स्थिति परिदृश्य सहयोगी सरणी परीक्षण फ़ंक्शन देता हूं जो अन्य सभी औसत-केस परिदृश्यों की तुलना में सबसे अच्छा या बेहतर है।

/**
 * Tests if an array is an associative array.
 *
 * @param array $array An array to test.
 * @return boolean True if the array is associative, otherwise false.
 */
function is_assoc(array &$arr) {
    // don't try to check non-arrays or empty arrays
    if (FALSE === is_array($arr) || 0 === ($l = count($arr))) {
        return false;
    }

    // shortcut by guessing at the beginning
    reset($arr);
    if (key($arr) !== 0) {
        return true;
    }

    // shortcut by guessing at the end
    end($arr);
    if (key($arr) !== $l-1) {
        return true;
    }

    // rely on php to optimize test by reference or fast compare
    return array_values($arr) !== $arr;
}

से https://3v4l.org/rkieX :

<?php

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

// method_2 was DQ; did not actually work

// array_keys
function method_3(Array &$arr) {
    return array_keys($arr) === range(0, count($arr) - 1);
}

// foreach
function method_4(Array &$arr) {
    $idx = 0;
    foreach( $arr as $key => $val ){
        if( $key !== $idx )
            return FALSE;
        ++$idx;
    }
    return TRUE;
}

// guessing
function method_5(Array &$arr) {
    global $METHOD_5_KEY;
    $i = 0;
    $l = count($arr)-1;

    end($arr);
    if ( key($arr) !== $l )
        return FALSE;

    reset($arr);
    do {
        if ( $i !== key($arr) )
            return FALSE;
        ++$i;
        next($arr);
    } while ($i < $l);
    return TRUE;
}

// naieve
function method_6(Array &$arr) {
    $i = 0;
    $l = count($arr);
    do {
        if ( NULL === @$arr[$i] )
            return FALSE;
        ++$i;
    } while ($i < $l);
    return TRUE;
}

// deep reference reliance
function method_7(Array &$arr) {
    return array_keys(array_values($arr)) === array_keys($arr);
}


// organic (guessing + array_values)
function method_8(Array &$arr) {
    reset($arr);
    if ( key($arr) !== 0 )
        return FALSE;

    end($arr);
    if ( key($arr) !== count($arr)-1 )
        return FALSE;

    return array_values($arr) === $arr;
}

function benchmark(Array &$methods, Array &$target, $expected){    
    foreach($methods as $method){
        $start = microtime(true);
        for ($i = 0; $i < 2000; ++$i) {
            //$dummy = call_user_func($method, $target);
            if ( $method($target) !== $expected ) {
                echo "Method $method is disqualified for returning an incorrect result.\n";
                unset($methods[array_search($method,$methods,true)]);
                $i = 0;
                break;
            }
        }
        if ( $i != 0 ) {
            $end = microtime(true);
            echo "Time taken with $method = ".round(($end-$start)*1000.0,3)."ms\n";
        }
    }
}



$true_targets = [
    'Giant array' => range(0, 500),
    'Tiny array' => range(0, 20),
];


$g = range(0,10);
unset($g[0]);

$false_targets = [
    'Large array 1' => range(0, 100) + ['a'=>'a'] + range(101, 200),
    'Large array 2' => ['a'=>'a'] + range(0, 200),
    'Tiny array' => range(0, 10) + ['a'=>'a'] + range(11, 20),
    'Gotcha array' => $g,
];

$methods = [
    'method_1',
    'method_3',
    'method_4',
    'method_5',
    'method_6',
    'method_7',
    'method_8'
];


foreach($false_targets as $targetName => $target){
    echo "==== Benchmark using $targetName expecing FALSE ====\n";
    benchmark($methods, $target, false);
    echo "\n";
}
foreach($true_targets as $targetName => $target){
    echo "==== Benchmark using $targetName expecting TRUE ====\n";
    benchmark($methods, $target, true);
    echo "\n";
}

2

यहाँ मैं प्रयोग विधि है:

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) );

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


2
<?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);
}

?>

इन दोनों उदाहरणों में, जिन्होंने सबसे अधिक अंक प्राप्त किए हैं, जैसे सरणियों के साथ सही ढंग से काम नहीं करते हैं $array = array('foo' => 'bar', 1)


+1 आपका is_list () IMO सबसे अच्छा उत्तर है। कुछ लोगों के पास समय और स्थान की जटिलता और देशी बनाम PHP स्क्रिप्टेड फ़ंक्शन के बारे में कोई सुराग नहीं है ...
e2-e4

2

यह भी काम करेगा ( डेमो ):

function array_has_numeric_keys_only(array $array)
{
    try {
        SplFixedArray::fromArray($array, true);
    } catch (InvalidArgumentException $e) {
        return false;
    }
    return true;
}

कृपया ध्यान दें कि इस उत्तर का मुख्य बिंदु SplFixedArrayआपको इस प्रकार के परीक्षणों के लिए अपवादों के अस्तित्व के बारे में सूचित करना है और आपको प्रोत्साहित नहीं करना है।


2

मुझे लगता है कि स्केलर ऐरे की परिभाषा एप्लिकेशन द्वारा अलग-अलग होगी। यही है, कुछ अनुप्रयोगों को एक स्केलर सरणी के रूप में अर्हता प्राप्त करने की अधिक सख्त भावना की आवश्यकता होगी, और कुछ अनुप्रयोगों को अधिक ढीले अर्थ की आवश्यकता होगी।

नीचे मैं अलग-अलग सख्ती के 3 तरीके प्रस्तुत करता हूं।

<?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 <DavidPFarrell@gmail.com>
 */

/**
 * 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;
}

2

एक और तेजी से स्रोत सेjson_encode(और bson_encode) की फ़िट एन्कोडिंग । तो जावास्क्रिप्ट ऐरे अनुपालन है।

function isSequential($value){
    if(is_array($value) || ($value instanceof \Countable && $value instanceof \ArrayAccess)){
        for ($i = count($value) - 1; $i >= 0; $i--) {
            if (!isset($value[$i]) && !array_key_exists($i, $value)) {
                return false;
            }
        }
        return true;
    } else {
        throw new \InvalidArgumentException(
            sprintf('Data type "%s" is not supported by method %s', gettype($value), __METHOD__)
        );
    }
}

1
क्यों issetऔर array_key_existsकैसे? उत्तरार्द्ध पर्याप्त नहीं होगा?
mcfedr

@mcfedr हाँ, यह होगा - isset()यहाँ जाँच पूरी तरह से निरर्थक है।
मार्क अमेरी

प्रदर्शन कारणों की वजह से @mcfedr, @ मार्क-अमेरी। isset()से तेज है array_key_exists()। देख ilia.ws/archives/...
lazycommit

@lazycommit यह आपके सरणी पर निर्भर करता है फिर चाहे इसके साथ बेहतर हो या न हो, यह नहीं कि इसकी संभावना बहुत सारे के साथ एक सरणी है null, लेकिन फिर यह भी संभावना नहीं है कि आपके पास सरणी काफी बड़ी है कि ध्यान देने योग्य प्रदर्शन अंतर होगा दोनों चेक का उपयोग करके
mcfedr

2
आप अगर यह फिट जांच करने की आवश्यकता है, तो json_encode, तो आप बस श्रृंखला का पहला प्रतीक, द्वारा दिया जांच कर सकता है json_encode($your_arr)- यह है कि क्या [या {;-)
PILAT

2

क्या इसका समाधान हो सकता है?

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

कैविएट स्पष्ट रूप से है कि एरे कर्सर को रीसेट किया गया है, लेकिन मैं कहूंगा कि संभवतः फ़ंक्शन का उपयोग किया जाता है इससे पहले कि ऐरे भी ट्रैवर्स किया गया है या उपयोग किया गया है।


यह फ़ंक्शन दोनों के लिए गलत है array("a", "b")और array("a", "b" => "B")चूंकि यह केवल पहली कुंजी की जांच करता है। BTW, is_longका सिर्फ एक उपनाम हैis_int
पैंग

1
काफी स्पष्ट रूप से मुझे लगता है कि यह अधिकांश मामलों में बहुत प्रभावी होगा, और विकल्पों की तुलना में कहीं अधिक कुशल है। यदि आप इस पद्धति के परिणामों को समझते हैं, और यह महसूस करते हैं कि यह आपके लिए काम करेगा, तो यह सबसे अच्छा विकल्प है।
गेरशोम

यह केवल गलत है; यह केवल पहली कुंजी को देखता है।
मार्क अमेरी

@ मार्की सवाल ने पूछा कि विशुद्ध रूप से साहचर्य सरणियों से विशुद्ध रूप से अनुक्रमिक सरणियों को कैसे अलग किया जाए । यह उत्तर बिल्कुल यही करता है और उन सभी में सबसे कुशल है। मिश्रित सरणियों के लिए अपरिभाषित व्यवहार करना सवाल के संदर्भ में पूरी तरह से ठीक है। +1
टोबिया जूल

@ टोबिया मुझे नहीं लगता कि ज्यादातर लोग [7 => 'foo', 2 => 'bar']"मिश्रित" सरणी के रूप में, जो कि आंशिक रूप से नहीं बल्कि "विशुद्ध रूप से" अनुक्रमिक है , आप को वर्गीकृत करने से सहमत होंगे । यह मेरे लिए शब्दों का स्पष्ट रूप से गलत उपयोग जैसा लगता है।
मार्क अमेरी

2

यहां बहुत सारे समाधान सुरुचिपूर्ण और सुंदर हैं, लेकिन अच्छी तरह से पैमाने नहीं हैं, और स्मृति गहन या सीपीयू गहन हैं। अधिकांश तुलना के दोनों ओर से इस समाधान के साथ स्मृति में 2 नए डेटा पॉइंट बना रहे हैं। बड़ा सरणी कठिन और लंबी प्रक्रिया और मेमोरी का उपयोग करता है, और आप शॉर्ट सर्किट मूल्यांकन का लाभ खो देते हैं। मैंने कुछ अलग विचारों के साथ कुछ परीक्षण किया। यह महंगा होने के साथ array_key_exists से बचने की कोशिश कर रहा है, और तुलना करने के लिए नए बड़े डेटासेट बनाने से भी बच रहा है। मुझे लगता है कि एक सरणी अनुक्रमिक है, तो यह बताने का एक सरल तरीका है।

public function is_sequential( $arr = [] ){
    if( !is_array( $arr ) || empty( $arr ) ) return false;

    $i = 0;

    $total = count( $arr );

    foreach( $arr as $key => $value ) if( $key !== $i++ ) return false;

    return true;
}

आप मुख्य सरणी पर एक ही गिनती चलाते हैं और एक पूर्णांक संग्रहीत करते हैं। फिर आप सरणी के माध्यम से लूप करते हैं और काउंटर को पुनरावृत्त करते हुए एक सटीक मिलान की जांच करते हैं। आपको 1 से गिनना चाहिए। यदि यह विफल रहता है तो यह शॉर्ट सर्किट हो जाएगा जो आपको गलत होने पर प्रदर्शन को बढ़ावा देता है।

मूल रूप से मैंने इसे लूप के लिए किया और isset ($ arrest [$ i]) के लिए जाँच की, लेकिन यह अशक्त कुंजियों का पता नहीं लगाएगा, जिनके लिए array_key_exists की आवश्यकता है, और जैसा कि हम जानते हैं कि गति के लिए उपयोग करने के लिए सबसे खराब फ़ंक्शन है।

लगातार चलने के माध्यम से चर के साथ अद्यतन करने के लिए itter के साथ जाँच करने के लिए यह पूर्णांक आकार कभी नहीं बढ़ रहा है चलो PHP का उपयोग करें यह स्मृति अनुकूलन, कैशिंग और कचरा संग्रह में बनाया गया है ताकि आप बहुत कम संसाधन उपयोग पर रख सकें।

इसके अलावा, मैं तर्क दूंगा कि एक फॉर्च्यू में array_keys का उपयोग करना मूर्खतापूर्ण है जब आप बस $ कुंजी => $ मूल्य चला सकते हैं और कुंजी की जांच कर सकते हैं। नया डेटा पॉइंट क्यों बनाएं? एक बार जब आप ऐरे कीज को दूर कर लेते हैं तो आपने तुरंत अधिक मेमोरी खा ली है।


1

उत्तर पहले से ही दिए गए हैं, लेकिन प्रदर्शन के बारे में बहुत अधिक कीटाणुशोधन है। मैंने यह छोटी बेंचमार्क स्क्रिप्ट लिखी है, जो बताती है कि फॉरच विधि सबसे तेज़ है।

अस्वीकरण: निम्नलिखित तरीकों को अन्य उत्तरों से कॉपी-पेस्ट किया गया था

<?php

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

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

function method_3(Array &$arr) {
    return array_keys($arr) === range(0, count($arr) - 1);
}

function method_4(Array &$arr) {
    $idx = 0;
    foreach( $arr as $key => $val ){
        if( $key !== $idx )
            return FALSE;
        $idx++;
    }
    return TRUE;
}




function benchmark(Array $methods, Array &$target){    
    foreach($methods as $method){
        $start = microtime(true);
        for ($i = 0; $i < 1000; $i++)
            $dummy = call_user_func($method, $target);

        $end = microtime(true);
        echo "Time taken with $method = ".round(($end-$start)*1000.0,3)."ms\n";
    }
}



$targets = [
    'Huge array' => range(0, 30000),
    'Small array' => range(0, 1000),
];
$methods = [
    'method_1',
    'method_2',
    'method_3',
    'method_4',
];
foreach($targets as $targetName => $target){
    echo "==== Benchmark using $targetName ====\n";
    benchmark($methods, $target);
    echo "\n";
}

परिणाम:

==== Benchmark using Huge array ====
Time taken with method_1 = 5504.632ms
Time taken with method_2 = 4509.445ms
Time taken with method_3 = 8614.883ms
Time taken with method_4 = 2720.934ms

==== Benchmark using Small array ====
Time taken with method_1 = 77.159ms
Time taken with method_2 = 130.03ms
Time taken with method_3 = 160.866ms
Time taken with method_4 = 69.946ms

1

या आप इसका उपयोग कर सकते हैं:

Arr::isAssoc($array)

जो चेक करेगा कि क्या सरणी में कोई गैर-संख्यात्मक कुंजी है या:

Arr:isAssoc($array, true)

यह जाँचने के लिए कि सरणी सख्ती से अनुक्रमिक है (इसमें ऑटो जेनरेट की गई कुंजी 0 से n-1 है )

इस पुस्तकालय का उपयोग करना ।


0

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

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 :)

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


1
आम तौर पर सिर्फ यह मानते हुए कि सरणी वांछित रास्ता है। लेकिन मेरे मामले में मैं एक बहुआयामी सरणी के माध्यम से पाशन कर रहा हूं और आउटपुट को स्वरूपित कर रहा हूं जिसके आधार पर किसी दिए गए नोड का प्रकार किस प्रकार का है।
विल्को ऑक्ट

0

मैं सरणी की कुंजियों और सरणी के array_values ​​() के परिणाम की कुंजी के बीच अंतर की तुलना करता हूं, जो हमेशा पूर्णांक सूचक के साथ एक सरणी होगी। यदि कुंजियाँ समान हैं, तो यह एक सहयोगी सरणी नहीं है।

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

-1; इस का उपयोग करता है O(n)अतिरिक्त मेमोरी जब $arrayहै nआइटम, और लेखन (someboolean) ? false : trueके बजाय !somebooleanभयानक है और अनावश्यक रूप से अत्यधिक शब्द।
मार्क अमेरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.