forked from jorgecasas/php-ml
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new class Set for simple Set-theoretical operations
### Features * Works only with primitive types int, float, string * Implements set theortic operations union, intersection, complement * Modifies set by adding, removing elements * Implements \IteratorAggregate for use in loops ### Implementation details Based on array functions: * array_diff, * array_merge, * array_intersection, * array_unique, * array_values, * sort. ### Drawbacks * **Do not work with objects.** * Power set and Cartesian product returning array of Set
- Loading branch information
Showing
3 changed files
with
431 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# Set | ||
|
||
Class that wraps PHP arrays containing primitive types to mathematical sets. | ||
|
||
### Creation | ||
|
||
To create Set use flat arrays containing primitives only: | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set([1, 2, 2, 3, 1.1, -1, -10]); | ||
$set->toArray(); | ||
// return [-10, -1, 1, 1.1, 2, 3] | ||
$set = new Set(['B', '', 'A']); | ||
$set->toArray(); | ||
// return ['', 'A', 'B'] | ||
``` | ||
|
||
Injected array is sorted by SORT_ASC, duplicates are removed and index is rewritten. | ||
|
||
### Union | ||
|
||
Create the union of two Sets: | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$union = Set::union(new Set([1, 3]), new Set([1, 2])); | ||
$union->toArray(); | ||
//return [1, 2, 3] | ||
``` | ||
|
||
### Intersection | ||
|
||
Create the intersection of two Sets: | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$intersection = Set::intersection(new Set(['A', 'C']), new Set(['B', 'C'])); | ||
$intersection->toArray(); | ||
//return ['C'] | ||
``` | ||
|
||
### Complement | ||
|
||
Create the set-theoretic difference of two Sets: | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$difference = Set::difference(new Set(['A', 'B', 'C']), new Set(['A'])); | ||
$union->toArray(); | ||
//return ['B', 'C'] | ||
``` | ||
|
||
### Adding elements | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set([1, 2]); | ||
$set->addAll([3]); | ||
$set->add(4); | ||
$set->toArray(); | ||
//return [1, 2, 3, 4] | ||
``` | ||
|
||
### Removing elements | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set([1, 2]); | ||
$set->removeAll([2]); | ||
$set->remove(1); | ||
$set->toArray(); | ||
//return [] | ||
``` | ||
|
||
### Check membership | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set([1, 2]); | ||
$set->containsAll([2, 3]); | ||
//return false | ||
$set->contains(1); | ||
//return true | ||
``` | ||
|
||
### Cardinality | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set([1, 2]); | ||
$set->cardinality(); | ||
//return 2 | ||
``` | ||
|
||
### Is empty | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set(); | ||
$set->isEmpty(); | ||
//return true | ||
``` | ||
|
||
### Working with loops | ||
|
||
``` | ||
use \Phpml\Math\Set; | ||
$set = new Set(['A', 'B', 'C']); | ||
foreach($set as $element) { | ||
echo "$element, "; | ||
} | ||
// echoes A, B, C | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Phpml\Math; | ||
|
||
class Set implements \IteratorAggregate | ||
{ | ||
/** | ||
* @var string[]|int[]|float[] | ||
*/ | ||
private $elements; | ||
|
||
/** | ||
* @param string[]|int[]|float[] $elements | ||
*/ | ||
public function __construct(array $elements = []) | ||
{ | ||
$this->elements = self::sanitize($elements); | ||
} | ||
|
||
/** | ||
* Creates the union of A and B. | ||
* | ||
* @param Set $a | ||
* @param Set $b | ||
* | ||
* @return Set | ||
*/ | ||
public static function union(Set $a, Set $b) : Set | ||
{ | ||
return new self(array_merge($a->toArray(), $b->toArray())); | ||
} | ||
|
||
/** | ||
* Creates the intersection of A and B. | ||
* | ||
* @param Set $a | ||
* @param Set $b | ||
* | ||
* @return Set | ||
*/ | ||
public static function intersection(Set $a, Set $b) : Set | ||
{ | ||
return new self(array_intersect($a->toArray(), $b->toArray())); | ||
} | ||
|
||
/** | ||
* Creates the difference of A and B. | ||
* | ||
* @param Set $a | ||
* @param Set $b | ||
* | ||
* @return Set | ||
*/ | ||
public static function difference(Set $a, Set $b) : Set | ||
{ | ||
return new self(array_diff($a->toArray(), $b->toArray())); | ||
} | ||
|
||
/** | ||
* Creates the Cartesian product of A and B. | ||
* | ||
* @param Set $a | ||
* @param Set $b | ||
* | ||
* @return Set[] | ||
*/ | ||
public static function cartesian(Set $a, Set $b) : array | ||
{ | ||
$cartesian = []; | ||
|
||
foreach ($a as $multiplier) { | ||
foreach ($b as $multiplicand) { | ||
$cartesian[] = new self(array_merge([$multiplicand], [$multiplier])); | ||
} | ||
} | ||
|
||
return $cartesian; | ||
} | ||
|
||
/** | ||
* Creates the power set of A. | ||
* | ||
* @param Set $a | ||
* | ||
* @return Set[] | ||
*/ | ||
public static function power(Set $a) : array | ||
{ | ||
$power = [new self()]; | ||
|
||
foreach ($a as $multiplicand) { | ||
foreach ($power as $multiplier) { | ||
$power[] = new self(array_merge([$multiplicand], $multiplier->toArray())); | ||
} | ||
} | ||
|
||
return $power; | ||
} | ||
|
||
/** | ||
* Removes duplicates and rewrites index. | ||
* | ||
* @param string[]|int[]|float[] $elements | ||
* | ||
* @return string[]|int[]|float[] | ||
*/ | ||
private static function sanitize(array $elements) : array | ||
{ | ||
sort($elements, SORT_ASC); | ||
|
||
return array_values(array_unique($elements, SORT_ASC)); | ||
} | ||
|
||
/** | ||
* @param string|int|float $element | ||
* | ||
* @return Set | ||
*/ | ||
public function add($element) : Set | ||
{ | ||
return $this->addAll([$element]); | ||
} | ||
|
||
/** | ||
* @param string[]|int[]|float[] $elements | ||
* | ||
* @return Set | ||
*/ | ||
public function addAll(array $elements) : Set | ||
{ | ||
$this->elements = self::sanitize(array_merge($this->elements, $elements)); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* @param string|int|float $element | ||
* | ||
* @return Set | ||
*/ | ||
public function remove($element) : Set | ||
{ | ||
return $this->removeAll([$element]); | ||
} | ||
|
||
/** | ||
* @param string[]|int[]|float[] $elements | ||
* | ||
* @return Set | ||
*/ | ||
public function removeAll(array $elements) : Set | ||
{ | ||
$this->elements = self::sanitize(array_diff($this->elements, $elements)); | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* @param string|int|float $element | ||
* | ||
* @return bool | ||
*/ | ||
public function contains($element) : bool | ||
{ | ||
return $this->containsAll([$element]); | ||
} | ||
|
||
/** | ||
* @param string[]|int[]|float[] $elements | ||
* | ||
* @return bool | ||
*/ | ||
public function containsAll(array $elements) : bool | ||
{ | ||
return !array_diff($elements, $this->elements); | ||
} | ||
|
||
/** | ||
* @return string[]|int[]|float[] | ||
*/ | ||
public function toArray() : array | ||
{ | ||
return $this->elements; | ||
} | ||
|
||
/** | ||
* @return \ArrayIterator | ||
*/ | ||
public function getIterator() : \ArrayIterator | ||
{ | ||
return new \ArrayIterator($this->elements); | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
public function isEmpty() : bool | ||
{ | ||
return $this->cardinality() == 0; | ||
} | ||
|
||
/** | ||
* @return int | ||
*/ | ||
public function cardinality() : int | ||
{ | ||
return count($this->elements); | ||
} | ||
} |
Oops, something went wrong.