Implementing the Set Data Structure in PHP

in php •  6 years ago 

Unlike Javascript,
PHP does not have a native Set object built in. So let us implement one!

What are Set objects good for

In short: a Set is a data structure which only holds unique values. They can be mixed types (language depending), but all are unique and only values are present, no keys.
Good use cases for sets include;

  1. A list of usernames.
  2. Filtering out unique values in a data set (eg. all locations from a csv)

The interface

The interface for a set object looks like;

interface SetInterface
{
    public function has($item);

    public function add($item);

    public function delete($item);

    public function clear();
    
    public function values();
}

The API

The API for this data structure will look like;

$set = new Set([1, 2, 'three', 'four'])
echo $set->has('three'); // true
echo $set->has('FIVE'); // false
$set-put('FIVE');
echo $set->has('FIVE'); // true

$set-put('FIVE');
$set-put('FIVE');
$set-put('FIVE');
$set-put('FIVE');

foreach($set as $item) {
    // do something with $item
}

// OR export the unique values into an array
// notice that we pushed 'FIVE' four times,
// but it only appears once

$set->values(); // [1, 2, 'three', 'four', 'FIVE']

The Code

<?php

class Set implements \ArrayAccess, SetInterface {

    public $length;
    protected $data;
    protected $stub = 1; // this is used as the value in the assoc array, we are disinterested in this

    public function __construct(Array $arr) {
        $this->length = count($arr);
        foreach ($arr as $item) {
            // We are using a pointer to save on memory
            $this->data[$item] = &$this->stub;
        }
    }

    public function has($item) {
        return isset($this->data[$item]);
    }

    public function add($item) {
        $this->data[$item] = &$this->stub;
        $this->length = count($this->data);
    }

    public function delete($item) {
        unset($this->data[$item]);
        $this->length = count($this->data);
    }

    public function clear() {
        $this->data = [];
        $this->length = 0;
    }

    public function values() {
        return array_keys($this->data);
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

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

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

    public function offsetGet($offset) {
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }
}

A note on ArrayAccess

Implementing the ArrayAccess interface allows us to loop around our object as though it were an array, and can come in pretty handy.

$set = new Set([1,2,3,4]);

foreach($set as $item) {
    // do something with $item
}
Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Hello @jmackenzie91! This is a friendly reminder that you can download Partiko today and start earning Steem easier than ever before!

Partiko is a fast and beautiful mobile app for Steem. You can login using your Steem account, browse, post, comment and upvote easily on your phone!

You can even earn up to 3,000 Partiko Points per day, and easily convert them into Steem token!

Download Partiko now using the link below to receive 1000 Points as bonus right away!

https://partiko.app/referral/partiko

Congratulations @jmackenzie91! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 1 year!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!