1 <?php 2 3 declare(strict_types=1); 4 5 namespace Phpml\Math; 6 7 use ArrayIterator; 8 use IteratorAggregate; 9 10 class Set implements IteratorAggregate 11 { 12 /** 13 * @var string[]|int[]|float[]|bool[] 14 */ 15 private $elements = []; 16 17 /** 18 * @param string[]|int[]|float[]|bool[] $elements 19 */ 20 public function __construct(array $elements = []) 21 { 22 $this->elements = self::sanitize($elements); 23 } 24 25 /** 26 * Creates the union of A and B. 27 */ 28 public static function union(self $a, self $b): self 29 { 30 return new self(array_merge($a->toArray(), $b->toArray())); 31 } 32 33 /** 34 * Creates the intersection of A and B. 35 */ 36 public static function intersection(self $a, self $b): self 37 { 38 return new self(array_intersect($a->toArray(), $b->toArray())); 39 } 40 41 /** 42 * Creates the difference of A and B. 43 */ 44 public static function difference(self $a, self $b): self 45 { 46 return new self(array_diff($a->toArray(), $b->toArray())); 47 } 48 49 /** 50 * Creates the Cartesian product of A and B. 51 * 52 * @return Set[] 53 */ 54 public static function cartesian(self $a, self $b): array 55 { 56 $cartesian = []; 57 58 foreach ($a as $multiplier) { 59 foreach ($b as $multiplicand) { 60 $cartesian[] = new self(array_merge([$multiplicand], [$multiplier])); 61 } 62 } 63 64 return $cartesian; 65 } 66 67 /** 68 * Creates the power set of A. 69 * 70 * @return Set[] 71 */ 72 public static function power(self $a): array 73 { 74 $power = [new self()]; 75 76 foreach ($a as $multiplicand) { 77 foreach ($power as $multiplier) { 78 $power[] = new self(array_merge([$multiplicand], $multiplier->toArray())); 79 } 80 } 81 82 return $power; 83 } 84 85 /** 86 * @param string|int|float|bool $element 87 */ 88 public function add($element): self 89 { 90 return $this->addAll([$element]); 91 } 92 93 /** 94 * @param string[]|int[]|float[]|bool[] $elements 95 */ 96 public function addAll(array $elements): self 97 { 98 $this->elements = self::sanitize(array_merge($this->elements, $elements)); 99 100 return $this; 101 } 102 103 /** 104 * @param string|int|float $element 105 */ 106 public function remove($element): self 107 { 108 return $this->removeAll([$element]); 109 } 110 111 /** 112 * @param string[]|int[]|float[] $elements 113 */ 114 public function removeAll(array $elements): self 115 { 116 $this->elements = self::sanitize(array_diff($this->elements, $elements)); 117 118 return $this; 119 } 120 121 /** 122 * @param string|int|float $element 123 */ 124 public function contains($element): bool 125 { 126 return $this->containsAll([$element]); 127 } 128 129 /** 130 * @param string[]|int[]|float[] $elements 131 */ 132 public function containsAll(array $elements): bool 133 { 134 return count(array_diff($elements, $this->elements)) === 0; 135 } 136 137 /** 138 * @return string[]|int[]|float[]|bool[] 139 */ 140 public function toArray(): array 141 { 142 return $this->elements; 143 } 144 145 public function getIterator(): ArrayIterator 146 { 147 return new ArrayIterator($this->elements); 148 } 149 150 public function isEmpty(): bool 151 { 152 return $this->cardinality() === 0; 153 } 154 155 public function cardinality(): int 156 { 157 return count($this->elements); 158 } 159 160 /** 161 * Removes duplicates and rewrites index. 162 * 163 * @param string[]|int[]|float[]|bool[] $elements 164 * 165 * @return string[]|int[]|float[]|bool[] 166 */ 167 private static function sanitize(array $elements): array 168 { 169 sort($elements, SORT_ASC); 170 171 return array_values(array_unique($elements, SORT_ASC)); 172 } 173 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body