# array position isfirst / islast / valid ?

- Thread: https://externals.io/message/46593
- Original archive: https://news-web.php.net/php.internals/46593
- Started by Oskar Eisemuth on 2010-01-02T16:47:10+00:00
- Messages: 4
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #46593 — Oskar Eisemuth — 2010-01-02T16:47:10+00:00

URL: https://externals.io/message/46593#46593

Hello

Would it be possible to add functions to know the relative internal array position?

I found "[PHP-DEV] RFC array functions" from 2006, but nothing really changed.

The need to use next, prev in combination is ridiculous compared to a clean array_hasmore or array_pos_islast, as the internals already know this.
To get an array_valid_position or array_pos_isvalid wouldn't be bad either.

So would it possible to introduce:

array_pos_isfirst(&  $array)
array_pos_islast(&  $array)
array_pos_isvalid(&  $array)


Best regards
Oskar Eisemuth

---

## #46594 — Kalle Sommer Nielsen — 2010-01-02T20:36:07+00:00

URL: https://externals.io/message/46593#46594 · In reply to: #46593

Hi Oskar

2010/1/2 Oskar Eisemuth <patchnow@gmail.com>:
> Hello
>
> Would it be possible to add functions to know the relative internal array
> position?
>
> I found "[PHP-DEV] RFC array functions" from 2006, but nothing really
> changed.
>
> The need to use next, prev in combination is ridiculous compared to a clean
> array_hasmore or array_pos_islast, as the internals already know this.
> To get an array_valid_position or array_pos_isvalid wouldn't be bad either.
>
> So would it possible to introduce:
>

How about just array_pos() if any. The remaining functions can easily
be implemented in userland like:

function array_pos_isfirst(Array &$array) {
 return array_pos($array) == 0;
}

function array_pos_islast(Array &$array) {
 return array_pos($array) == (sizeof($array) - 1);
}

I don't think it should be needed to add array_pos_isvalid(), since it
*shouldn't* be possible to point to an invalid position. Rather
"isset($array['key'])" should be used to check if a position is valid.



-- 
regrads,

Kalle Sommer Nielsen
kalle@php.net

---

## #46595 — mm w — 2010-01-02T22:32:38+00:00

URL: https://externals.io/message/46593#46595 · In reply to: #46593

<?php

interface FastEnumeration extends IteratorAggregate
{

};

interface FastEnumerator extends Iterator
{

};

define('EnumerationConcurrent', 0);
define('EnumerationReverse', 1);

class Enumerator implements FastEnumerator
{
	private $arr;
	private $reversed;
	
	function __construct(array &$arr, $reversed = 0) {
		$this->reversed  = $reversed;
		$this->arr = $arr;
		if ($this->reversed) {
			end($this->arr);
		}
	}
	
	public function first() {
		if ($this->reversed) {
			$cnt = count($this->arr);
			$idx = $cnt > 1 ? $cnt - 1 : 0;
		} else {
			$idx = 0;
		}
		return $this->arr[$idx];
	}
	
	public function `last()` {
		if ($this->reversed) {
			$idx = 0;
		} else {
			$cnt = count($this->arr);
			$idx = $cnt > 1 ? $cnt - 1 : 0;
		}
		return $this->arr[$idx];
	}
	
	public function isfirst() {
		if ($this->reversed) {
			$cnt = count($this->arr);
			$idx = $cnt > 1 ? $cnt - 1 : 0;
		} else {
			$idx = 0;
		}
		return key($this->arr) == $idx;
	}
	
	public function islast() {
		if ($this->reversed) {
			$idx = 0;
		} else {
			$cnt = count($this->arr);
			$idx = $cnt > 1 ? $cnt - 1 : 0;
		}
		return key($this->arr) == $idx;
	}
	
	public function `rewind()` {
		if ($this->reversed) {
			end($this->arr);
		} else {
			reset($this->arr);
		}
	}
	
	public function `current()` {
		return current($this->arr);
	}
	
	public function `key()` {
		return key($this->arr);
	}
	
	public function `end()` {
		if ($this->reversed) {
			reset($this->arr);
		} else {
			end($this->arr);
		}
	}


	public function `next()` {
		if ($this->reversed) {
			return prev($this->arr);
		} else {
			return next($this->arr);
		}
	}
	
	public function `prev()` {
		if ($this->reversed) {
			return next($this->arr);
		} else {
			return prev($this->arr);
		}
	}

	public function valid() {
		$current = $this->current();
		return  !empty($current) && $current != null;
	}
};

class MArray implements FastEnumeration
{
	private $arr;
	
	public function getIterator() {
		return new Enumerator($this->arr);
        }

	public function reverseEnumerator() {
		return new Enumerator($this->arr, EnumerationReverse);
	}

	public function concurrentEnumerator() {
		return new Enumerator($this->arr, EnumerationConcurrent);
    }

    // ...
};

/* EOF */ ?>


> Hello
>
> Would it be possible to add functions to know the relative internal array
> position?
>
> I found "[PHP-DEV] RFC array functions" from 2006, but nothing really
> changed.
>
> The need to use next, prev in combination is ridiculous compared to a clean
> array_hasmore or array_pos_islast, as the internals already know this.
> To get an array_valid_position or array_pos_isvalid wouldn't be bad either.
>
> So would it possible to introduce:
>
> array_pos_isfirst(&  $array)
> array_pos_islast(&  $array)
> array_pos_isvalid(&  $array)
>
>
> Best regards
> Oskar Eisemuth

---

## #46596 — Oskar Eisemuth — 2010-01-03T14:30:12+00:00

URL: https://externals.io/message/46593#46596 · In reply to: #46594

Hello


> How about just array_pos() if any. The remaining functions can easily
> be implemented in userland like:
>
> function array_pos_isfirst(Array&$array) {
>   return array_pos($array) == 0;
> }
>
> function array_pos_islast(Array&$array) {
>   return array_pos($array) == (sizeof($array) - 1);
> }
>
> I don't think it should be needed to add array_pos_isvalid(), since it
> *shouldn't* be possible to point to an invalid position. Rather
> "isset($array['key'])" should be used to check if a position is valid.
>
>    
Well, the internal Zend Hash doesn't know it's position as index, 
getting to know if the internal pointer is on the last or first entry is 
much easier as both ends are defined by  ht->pListHead and ht->pListTail.

Something like:

int zend_hash_pointer_is_head(HashTable *ht, HashPosition *pos) {
Bucket *p;
p = pos ? (*pos) : ht->pInternalPointer;
if (p == ht->pListHead) return 1;
return 0;
}

You really don't want to return memory pointers to user code so you 
would need to traverse the array to get some kind of index number.

array_pos_isvalid would be mapped to zend_hash_has_more_elements_ex, 
that is defined by checking zend_hash_get_current_key_type_ex returning 
HASH_KEY_NON_EXISTANT. Internally it means really check the pointer for 
null, so you could call it array_pos_isundefined too.

Generally you can use key($array) === null with the same effect. so this 
would only be for interface completeness and needs to move less data 
around then a `key()` call.

Best regards
Oskar Eisemuth
