Skip to content

Commit

Permalink
Update the Zip operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Aug 18, 2019
1 parent 8b9c53b commit 660f8ad
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 25 deletions.
6 changes: 5 additions & 1 deletion spec/drupol/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,12 @@ public function it_can_zip(): void
->beConstructedThrough('with', [\range('A', 'C')]);

$this
->zip('D', 'E', 'F')
->zip(['D', 'E', 'F'])
->shouldIterateAs([['A', 'D'], ['B', 'E'], ['C', 'F']]);

$this::with(['A', 'C', 'E'])
->zip(['B', 'D', 'F', 'H'])
->shouldIterateAs([['A', 'B'], ['C', 'D'], ['E', 'F'], [null, 'H']]);
}

public function it_is_initializable(): void
Expand Down
46 changes: 37 additions & 9 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,17 @@ final class Collection implements CollectionInterface
*/
public function all(): array
{
return \iterator_to_array($this->getIterator());
$result = [];

foreach ($this->getIterator() as $key => $item) {
if ($item instanceof CollectionInterface) {
$result[$key] = $item->all();
} else {
$result[$key] = $item;
}
}

return $result;
}

/**
Expand All @@ -64,9 +74,7 @@ public function append(...$items): CollectionInterface
public function apply(callable $callback): CollectionInterface
{
foreach ($this as $key => $item) {
$return = $callback($item, $key);

if (\is_bool($return) && false === $return) {
if (false === $callback($item, $key)) {
break;
}
}
Expand Down Expand Up @@ -98,6 +106,26 @@ public function combine($keys): CollectionInterface
return $this->run(Combine::with(...$keys));
}

/**
* {@inheritdoc}
*/
public function contains($key): bool
{
if (!\is_string($key) && \is_callable($key)) {
$placeholder = new \stdClass();

return $this->first($key, $placeholder) !== $placeholder;
}

foreach ($this as $value) {
if ($value === $key) {
return true;
}
}

return false;
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -361,7 +389,7 @@ public function walk(callable ...$callbacks): CollectionInterface
/**
* Create a new collection instance.
*
* @param null|array|callable|Closure|Collection $data
* @param null|array|callable|Closure|CollectionInterface $data
*
* @return \drupol\collection\Contract\Collection
*/
Expand Down Expand Up @@ -455,14 +483,14 @@ private static function getArrayableItems($items): array
*/
private function makeIterator($source): \Iterator
{
if (\is_array($source)) {
$source = new ArrayIterator($source);
if ($source instanceof CollectionInterface) {
return $source->getIterator();
}

if (\is_callable($source)) {
$source = $source();
return $source();
}

return $source;
return new ArrayIterator((array) $source);
}
}
7 changes: 7 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ public function collapse(): self;
*/
public function combine($keys): self;

/**
* @param mixed $key
*
* @return bool
*/
public function contains($key): bool;

/**
* {@inheritdoc}
*/
Expand Down
8 changes: 5 additions & 3 deletions src/Operation/Collapse.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ public function run(CollectionInterface $collection): CollectionInterface
{
return Collection::withClosure(
static function () use ($collection) {
foreach ($collection as $values) {
if (\is_array($values) || $values instanceof CollectionInterface) {
yield from $values;
foreach ($collection as $item) {
if (\is_array($item) || $item instanceof CollectionInterface) {
foreach ($item as $value) {
yield $value;
}
}
}
}
Expand Down
40 changes: 28 additions & 12 deletions src/Operation/Zip.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,36 @@ final class Zip extends Operation
*/
public function run(CollectionInterface $collection): CollectionInterface
{
$items = $this->parameters;
$iterables = $this->parameters;

return Collection::withClosure(
static function () use ($items, $collection) {
$iterator = $collection->getIterator();

/** @var \Iterator $itemsIterator */
$itemsIterator = Collection::with($items)->getIterator();

while ($iterator->valid()) {
yield [$iterator->current(), $itemsIterator->current()];

$itemsIterator->next();
$iterator->next();
static function () use ($iterables, $collection) {
$iterators = Collection::with(
Collection::with($iterables)
->map(
static function ($iterable) {
return Collection::with($iterable)->getIterator();
}
)
->prepend($collection->getIterator())
);

while ($iterators->map(static function (\Iterator $iterator) {
return $iterator->valid();
})->contains(true)) {
yield Collection::with(
$iterators->map(
static function (\Iterator $item) {
return $item->current();
}
)
)->all();

$iterators->apply(
static function (\Iterator $item): void {
$item->next();
}
);
}
}
);
Expand Down

0 comments on commit 660f8ad

Please sign in to comment.