diff --git a/src/Phaseolies/Support/Collection.php b/src/Phaseolies/Support/Collection.php index d59e10a..9134b09 100644 --- a/src/Phaseolies/Support/Collection.php +++ b/src/Phaseolies/Support/Collection.php @@ -761,4 +761,57 @@ public function partition(callable $callback): array new static($this->model, $failed) ]; } + + /** + * Get items not present in the given items. + * + * @param mixed $items + * @return static + */ + public function diff($items): self + { + $compare = $items instanceof self ? $items->all() : (array) $items; + + $result = []; + foreach ($this->data as $item) { + if (!in_array($item, $compare, true)) { + $result[] = $item; + } + } + + return new static($this->model, $result); + } + + /** + * Get items present in both this collection and given items + * + * @param mixed $items + * @return static + */ + public function intersect($items): self + { + $compare = $items instanceof self ? $items->all() : (array) $items; + + $result = []; + foreach ($this->data as $item) { + if (in_array($item, $compare, true)) { + $result[] = $item; + } + } + + return new static($this->model, $result); + } + + /** + * Execute a callback over the collection without modifying it. + * + * @param callable $callback + * @return $this + */ + public function tap(callable $callback): self + { + $callback($this); + + return $this; + } } diff --git a/tests/CollectionTest.php b/tests/CollectionTest.php index 4c1cdab..b46519c 100644 --- a/tests/CollectionTest.php +++ b/tests/CollectionTest.php @@ -1315,4 +1315,61 @@ public function testPartitionWithObjects() $this->assertCount(2, $active); $this->assertCount(1, $inactive); } + + public function testDiffReturnsItemsNotInOtherCollection() + { + $modelClass = get_class($this->makeTestModel(0, "")); + $collection1 = new Collection($modelClass, [1, 2, 3, 4, 5]); + $collection2 = new Collection($modelClass, [3, 4, 5, 6, 7]); + + $diff = $collection1->diff($collection2); + + $this->assertEquals([1, 2], $diff->all()); + } + + public function testDiffWithArray() + { + $modelClass = get_class($this->makeTestModel(0, "")); + $collection = new Collection($modelClass, [1, 2, 3, 4, 5]); + + $diff = $collection->diff([3, 4, 5]); + + $this->assertEquals([1, 2], $diff->all()); + } + + public function testIntersectReturnsCommonItems() + { + $modelClass = get_class($this->makeTestModel(0, "")); + $collection1 = new Collection($modelClass, [1, 2, 3, 4, 5]); + $collection2 = new Collection($modelClass, [3, 4, 5, 6, 7]); + + $intersect = $collection1->intersect($collection2); + + $this->assertEquals([3, 4, 5], $intersect->all()); + } + + public function testIntersectWithArray() + { + $modelClass = get_class($this->makeTestModel(0, "")); + $collection = new Collection($modelClass, [1, 2, 3, 4, 5]); + + $intersect = $collection->intersect([2, 3, 6]); + + $this->assertEquals([2, 3], $intersect->all()); + } + + public function testTapExecutesCallbackWithoutModifying() + { + $modelClass = get_class($this->makeTestModel(0, "")); + $collection = new Collection($modelClass, [1, 2, 3]); + + $tapped = null; + $result = $collection->tap(function ($col) use (&$tapped) { + $tapped = $col->count(); + }); + + $this->assertEquals(3, $tapped); + $this->assertSame($collection, $result); + $this->assertEquals([1, 2, 3], $collection->all()); + } }