tags:

views:

525

answers:

5

Is there a version of the PHP array class where all the elements must be distinct like, for instance, sets in Python?

A: 

You can use a special class, or array_unique to filter the duplicates.

erenon
+1  A: 

An array is an array, and for the most part yo can put anything into it. All keys must be unique. If you want to go and add a function that strips out duplicate values, that is very possible by simply doing a array_unique statement

Chacha102
+3  A: 

Nope. You could fake it by using an associative array where the keys are the elements in the "set" and the values are ignored.

John Kugelman
Note that this works only with strings and numbers, since these are the only legal types for array keys. You cannet have a 'set' of objects this way.
soulmerge
that's how it's routinely done in Lua. of course, Lua tables can use any value as a key, instead of being arbitrarily limited to numbers and strings
Javier
How you accomplish something in Lua has nothing to do with how you do it in PHP.
Zenham
You can json_encode the objects to use them as keys.
Joeri Sebrechts
+1  A: 

Here's a first-draft of an idea that could eventually work for what you want.

<?php

class DistinctArray implements IteratorAggregate, Countable, ArrayAccess
{
  protected $store = array();

  public function __construct( array $initialValues )
  {
    foreach ( $initialValues as $key => $value )
    {
      $this[$key] = $value;
    }
  }

  final public function offsetSet( $offset, $value )
  {
    if ( in_array( $value, $this->store, true ) )
    {
      throw new Exception( 'Values must be unique!' );
    }
    if ( null === $offset )
    {
      array_push( $this->store, $value );
    } else {
      $this->store[$offset] = $value;
    }
  }

  final public function offsetGet( $offset )
  {
    return $this->store[$offset];
  }

  final public function offsetExists( $offset )
  {
    return isset( $this->store[$offset] );
  }

  final public function offsetUnset( $offset )
  {
    unset( $this->store[$offset] );
  }

  final public function count()
  {
    return count( $this->store );
  }

  final public function getIterator()
  {
    return new ArrayIterator( $this->store );
  }
}

$test = new DistinctArray( array(
    'test' => 1
  , 'foo'  => 2
  , 'bar'  => 3
  , 'baz'  => '1'
  , 8      => 4
) );

try {
  $test[] = 5;
  $test[] = 6;
  $test['dupe'] = 1;
}
catch ( Exception $e )
{
  echo "Oops! ", $e->getMessage(), "<hr>";
}

foreach ( $test as $value )
{
  echo $value, '<br>';
}
Peter Bailey
+1  A: 

For objects that are not integers and strings: SplObjectStorage

The SplObjectStorage class provides a map from objects to data or, by ignoring data, an object set.

newacct
Objects are never integer or strings. They are objects ;)
Gordon