Question

How to Check if a PHP Array Is Associative or Sequential

phparrays

Question

In PHP, arrays can contain either numeric or string keys, and there is no separate built-in array type for lists versus associative maps in older PHP versions. What is an efficient way to check whether an array behaves like a list—that is, whether it contains only numeric keys starting at 0 in order?

For example, how can I distinguish between these two arrays?

$sequentialArray = [
    'apple', 'orange', 'tomato', 'carrot'
];

$assocArray = [
    'fruit1' => 'apple',
    'fruit2' => 'orange',
    'veg1' => 'tomato',
    'veg2' => 'carrot'
];

Short Answer

By the end of this page, you will understand how PHP array keys work, how to tell whether an array is sequential or associative, and which approaches are best in modern and older PHP versions. You will also see practical examples, common mistakes, and how this check is used in real applications.

Concept

PHP uses one array type for both:

  • Lists: values stored with numeric keys in order, usually starting at 0
  • Associative arrays: values stored with named keys

That means this is valid in PHP:

$items = ['a', 'b', 'c'];

and so is this:

$items = ['first' => 'a', 'second' => 'b'];

Internally, both are arrays.

The difference is in the keys.

A sequential array (often called a list) usually has keys like this:

[0, 1, 2, 3]

An associative array has keys like this:

['name', 'email', 'role']

or even numeric keys that are not a continuous sequence:

[1 => 'apple', 3 => 'orange']

That last example is important: even though the keys are numbers, it is not a proper list if your rule is “numeric keys starting at 0 with no gaps.”

This matters because real programs often need to know whether data should be processed as:

  • a collection of items, or
  • a key/value object-like structure

For example:

  • JSON encoding may produce different structures
  • validation may differ for lists and maps
  • APIs often expect one format or the other
  • loops and transformations may behave differently depending on the key shape

In modern PHP, the clearest built-in solution is:

array_is_list($array)

This was introduced in PHP 8.1 and checks exactly whether the array keys are 0 through n-1 in order.

Mental Model

Think of a PHP array like a set of labeled storage boxes.

  • A sequential array is like boxes on a shelf labeled 0, 1, 2, 3 with no missing numbers.
  • An associative array is like boxes labeled fruit1, fruit2, veg1, veg2.

If the labels are perfect shelf positions starting at 0, it is a list. If the labels are custom names, or the numbers skip around, it is associative for practical purposes.

Another way to think about it:

  • List = “a row of items”
  • Associative array = “a lookup table”

Your check is really asking:

Are these values arranged in a clean row, or are they stored by custom labels?

Take Quiz

Syntax and Examples

Modern PHP: array_is_list()

If you are using PHP 8.1 or later, use this:

$sequentialArray = ['apple', 'orange', 'tomato', 'carrot'];
$assocArray = [
    'fruit1' => 'apple',
    'fruit2' => 'orange',
    'veg1' => 'tomato',
    'veg2' => 'carrot'
];

var_dump(array_is_list($sequentialArray)); // true
var_dump(array_is_list($assocArray));      // false

This is the best option because it is:

  • readable
  • built into PHP
  • designed for exactly this purpose

Older PHP versions

If array_is_list() is not available, a common approach is:

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

Example:

$sequentialArray = ['apple', 'orange', 'tomato', 'carrot'];
$assocArray = [
    'fruit1' => 'apple',
    'fruit2' => 'orange',
    'veg1' => 'tomato',
    'veg2' => 'carrot'
];

var_dump(is_list_array($sequentialArray)); // true
var_dump(is_list_array($assocArray));      // false

Why this works

array_keys($array)

returns the array's keys.

For a sequential array like:

['apple', 'orange', 'tomato']

PHP stores keys as:

[0, 1, 2]

Then this creates the expected list of keys:

range(0, count($array) - 1)

If both key lists match exactly, the array is sequential.

Handle the empty array correctly

A small edge case: range(0, -1) is not what you want for an empty array.

A safer version is:

function is_list_array(array $array): bool
{
    if ($array === []) {
        return true;
    }

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

An empty array is usually considered a valid list because it has no invalid keys.

Example with non-sequential numeric keys

$array = [1 => 'apple', 2 => 'orange'];

var_dump(array_is_list($array)); // false in PHP 8.1+

Even though the keys are numeric, the array is not a list because it does not start at 0.

Step by Step Execution

Consider this function:

function is_list_array(array $array): bool
{
    if ($array === []) {
        return true;
    }

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

$data = ['apple', 'orange', 'tomato'];
$result = is_list_array($data);
var_dump($result);

Here is what happens step by step:

  1. $data is created:

    ['apple', 'orange', 'tomato']
    

    PHP automatically gives it these keys:

    [0, 1, 2]
    
  2. is_list_array($data) is called.

  3. The function checks:

    $array === []
    

    This is false because the array is not empty.

  4. The function gets the keys:

    array_keys($array)
    

    Result:

    [0, 1, 2]
    
  5. The function builds the expected sequence:

    range(0, count($array) - 1)
    

    count($array) is 3, so this becomes:

    range(0, 2)
    

    Result:

    [0, 1, 2]
    
  6. PHP compares both arrays with ===:

    [0, 1, 2] === [0, 1, 2]
    

    This is true.

  7. The function returns true, so var_dump($result) prints:

    bool(true)
    

Now compare this with:

$data = [1 => 'apple', 2 => 'orange'];
  • array_keys($data) gives [1, 2]
  • range(0, count($data) - 1) gives [0, 1]
  • These do not match
  • The function returns false

Real World Use Cases

1. Choosing how to encode data for JSON

When sending data to a frontend or API, you may need to know whether something should be treated like a list or an object-like map.

$data = ['apple', 'orange'];

This behaves like a collection of values.

But this:

$data = ['first' => 'apple', 'second' => 'orange'];

behaves more like labeled fields.

2. Validating API input

Suppose an endpoint expects a list of user IDs:

[12, 18, 25]

You may reject input like:

['admin' => 12, 'editor' => 18]

because it is not the expected shape.

3. Processing form or configuration data

Some configuration values are key/value pairs:

[
    'host' => 'localhost',
    'port' => 3306
]

Others are just lists:

['cache', 'queue', 'mail']

The check helps you decide how to loop over the data.

4. Data normalization

When importing CSV, JSON, or database results, you may receive inconsistent structures. Detecting whether an array is a list helps normalize the data before further processing.

5. Recursive data walkers

In utility functions that inspect nested arrays, developers often treat lists and associative arrays differently when formatting, validating, or transforming data.

Take Quiz

Real Codebase Usage

In real projects, developers rarely check array type just for curiosity. They usually do it because the code must branch into different behavior.

Common patterns

Guard clauses

Reject invalid input early:

function processIds(array $ids): void
{
    if (!array_is_list($ids)) {
        throw new InvalidArgumentException('Expected a list of IDs.');
    }

    foreach ($ids as $id) {
        // Process each ID
    }
}

Validation

Frameworks and service classes often validate not just values, but also structure.

function validateTags(array $tags): bool
{
    if (!array_is_list($tags)) {
        return false;
    }

    foreach ($tags as $tag) {
        if (!is_string($tag)) {
            return false;
        }
    }

    return true;
}

Recursive formatting or transformation

function describeArray(array $data): string
{
    if (array_is_list($data)) {
        return 'list';
    }

    return 'associative array';
}

Defensive coding with external data

Data from APIs, JSON, and user input may look similar but have different key structures. Developers often check list shape before using foreach assumptions or before mapping values.

Why readability matters

A custom function like is_list_array() is fine in older PHP versions, but in modern codebases array_is_list() is better because other developers immediately understand the intent.

Common Mistakes

1. Assuming numeric keys always mean a list

This is wrong:

$array = [2 => 'apple', 3 => 'orange'];

These are numeric keys, but it is not a sequential list starting at 0.

2. Forgetting gaps in keys

Broken assumption:

$array = [0 => 'apple', 2 => 'orange'];

This is not a list because key 1 is missing.

3. Using isset($array[0]) as the only test

Broken example:

function isListWrong(array $array): bool
{
    return isset($array[0]);
}

Why it is wrong:

  • it only checks one key
  • it does not verify the rest of the keys
  • it fails for empty arrays

4. Ignoring the empty array case

Broken version:

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

For an empty array, this can behave unexpectedly because range(0, -1) is not the intended comparison.

Safer version:

function is_list_array(array $array): bool
{
    if ($array === []) {
        return true;
    }

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

5. Confusing insertion order with key sequence

An array can be added in order but still not be a proper list if keys were assigned manually.

$array = [];
$array[1] = 'apple';
$array[2] = 'orange';

This is ordered, but still not a list by the usual rule.

6. Using loose comparisons

Prefer strict comparison:

array_keys($array) === range(0, count($array) - 1)

instead of:

array_keys($array) == range(0, count($array) - 1)

Strict comparison avoids surprising type-related matches.

Comparisons

ApproachPHP VersionGood ForNotes
array_is_list($array)8.1+Modern projectsBest choice: built-in, readable, accurate
array_keys($array) === range(0, count($array) - 1)Older PHPCompatibilityCommon fallback, but handle empty arrays carefully
Loop through keys manuallyAnyPerformance-sensitive custom logicMore verbose, useful if you want full control
isset($array[0])AnyAlmost never sufficientNot a real list check

Associative vs sequential

TypeExampleIs it a list?Why
Sequential['a', 'b', 'c']YesKeys are 0, 1, 2
Associative['x' => 'a', 'y' => 'b']NoKeys are strings
Numeric but shifted[1 => 'a', 2 => 'b']NoDoes not start at 0
Numeric with gaps[0 => 'a', 2 => 'b']NoMissing key 1
Empty array[]Usually yesNo invalid keys exist

array_is_list() vs custom helper

Featurearray_is_list()Custom helper
ReadabilityExcellentGood if well named
Built-inYesNo
Works on older PHPNoYes
MaintenanceLowSlightly higher
Best for new codeYesOnly if needed for compatibility
Take Quiz

Cheat Sheet

Quick rule

A PHP array is a list if its keys are exactly:

0, 1, 2, ..., n-1

with no gaps and in order.

Best modern solution

array_is_list($array)
  • Available in PHP 8.1+
  • Returns true for sequential arrays
  • Returns false for associative or non-sequential arrays

Older PHP fallback

function is_list_array(array $array): bool
{
    if ($array === []) {
        return true;
    }

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

Examples

array_is_list(['a', 'b', 'c']);              // true
array_is_list(['x' => 'a', 'y' => 'b']);     // false
array_is_list([1 => 'a', 2 => 'b']);         // false
array_is_list([0 => 'a', 2 => 'b']);         // false
array_is_list([]);                           // true

Important edge cases

  • Numeric keys are not enough
  • Keys must start at 0
  • Keys must be continuous
  • Empty array is usually treated as a valid list

Avoid

isset($array[0])

This does not prove the array is a list.

Good use cases

  • validating API input
  • checking data structure shape
  • branching between list logic and map logic
  • preparing data for encoding or transformation

FAQ

How do I check if an array is associative in PHP?

A common approach is to check whether it is not a list:

$isAssociative = !array_is_list($array);

In older PHP versions, use a custom helper instead.

Is there a built-in PHP function for checking list arrays?

Yes. In PHP 8.1 and later, use:

array_is_list($array)

Are arrays with numeric keys always sequential?

No. Numeric keys like [1 => 'a', 2 => 'b'] are not sequential lists if they do not start at 0.

Does an empty array count as a list?

Usually yes. It contains no invalid keys, so it is generally treated as a valid empty list.

What is the difference between associative and sequential arrays in PHP?

A sequential array has keys 0 through n-1 in order. An associative array uses custom keys such as strings, or numeric keys that are not a continuous sequence.

Why does this matter when working with JSON or APIs?

Because your code may need to treat a collection of items differently from a key/value object structure. Validation and transformation often depend on that distinction.

What should I use in older PHP versions before 8.1?

Use a helper like this:

function is_list_array(array $array): bool
{
    if ($array === []) {
        return true;
    }

    return array_keys($array) === range(0, count($array) - 1);
}
Take Quiz

Mini Project

Description

Build a small PHP utility that inspects several arrays and reports whether each one is a sequential list or an associative array. This is useful for understanding how PHP treats array keys and for practicing reusable helper functions that can be used in validation or data processing code.

Goal

Create a script that checks multiple arrays and prints whether each one is a list or associative.

Requirements

  • Write a function that returns whether an array is a sequential list.
  • Treat an empty array as a valid list.
  • Test the function with at least four different arrays.
  • Print a readable label for each test case.
  • Include one example with numeric keys that are not sequential.
Take Quiz

Keep learning

Related questions

View more