Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add static method to create new Stream and allow instant chaining #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $isOdd = function($num) {
};

// Create our stream.
$stream = new phpstreams\Stream(fibonacci());
$stream = new phpstreams\Stream(fibonacci()); // or phpstreams\Stream::of(fibonacci());

// Finally, use these to create our result.
$oddFibo = $stream->filter($isOdd) // Keep only the odd numbers
Expand Down
13 changes: 13 additions & 0 deletions src/Collectors.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use phpstreams\collectors\AveragingCollector;
use phpstreams\collectors\ReducingCollector;
use phpstreams\collectors\MappingCollector;

/**
* Utility class containing various collectors.
Expand Down Expand Up @@ -70,4 +71,16 @@ function ($current, $element) use (&$first, $delimiter) {
return $current . $element;
});
}

/**
* Get a collector that maps keys and values.
*
* @param callable $keyMapper
* @param callable $valueMapper [optional] A value mapper. Defaults to pass-through mapper.
* @return Collector
*/
public static function mapping(callable $keyMapper, callable $valueMapper = null)
{
return new MappingCollector($keyMapper, $valueMapper);
}
}
26 changes: 26 additions & 0 deletions src/Stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ public function __construct($source)
$this->source = $source;
}

/**
* Create a new stream from a traversable source.
*
* @param Traversable|array $source The source to create the stream from.
* @throws InvalidStreamException if the given source is not usable as a stream.
*/
public static function of($source)
{
return new static($source);
}

/**
* Check whether a source is valid.
*
Expand Down Expand Up @@ -265,6 +276,21 @@ public function collect(Collector $collector)
return $collector->get();
}

/**
* Get first element from stream
*
* @param $defaultValue [optional] Default value to return if stream is empty
* @return first element if available, default value otherwise
*/
public function first($defaultValue = null)
{
foreach ($this as $value) {
return $value;
}

return $defaultValue;
}

/**
* Flatten the underlying stream.
*
Expand Down
61 changes: 61 additions & 0 deletions src/collectors/MappingCollector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace phpstreams\collectors;

use phpstreams\Collector;

/**
* Collector that maps array keys and values.
*
* @author Bartosz Schiller <[email protected]>
*/
class MappingCollector implements Collector
{
/**
* Mapped array
*
* @var array
*/
private $map = [];

/**
* Callable for mapping key
*
* @var callable
*/
private $keyMapper;

/**
* Callable for mapping value
*
* @var callable
*/
private $valueMapper;

public function __construct(callable $keyMapper, callable $valueMapper = null)
{
$this->keyMapper = $keyMapper;

if (!is_callable($valueMapper))
{
$valueMapper = function ($k, $v) {
return $v;
};
}

$this->valueMapper = $valueMapper;
}

public function add($key, $value)
{
$keyMapper = $this->keyMapper;
$valueMapper = $this->valueMapper;

$this->map[$keyMapper($key, $value)] = $valueMapper($key, $value);
}

public function get()
{
return $this->map;
}
}
34 changes: 34 additions & 0 deletions tests/unit/CollectorsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,38 @@ public function testReducing()

$this->assertEquals(24, $instance->get());
}

public function testMapping()
{
$instance = Collectors::mapping(function ($k, $v) {
return $k . "a";
}, function($k, $v) {
return $v + 10;
});

$instance->add("a", 2);
$instance->add("b", 3);
$instance->add("c", 4);

$this->assertEquals([
"aa" => 12,
"ba" => 13,
"ca" => 14
], $instance->get());


$instance = Collectors::mapping(function ($k, $v) {
return $k . "a";
});

$instance->add("a", 2);
$instance->add("b", 3);
$instance->add("c", 4);

$this->assertEquals([
"aa" => 2,
"ba" => 3,
"ca" => 4
], $instance->get());
}
}
31 changes: 31 additions & 0 deletions tests/unit/StreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public function testConstructor()
$this->assertInstanceOf("Traversable", $value);
}

public function testStaticCreation()
{
$value = Stream::of([]);

$this->assertInstanceOf("Traversable", $value);
}

/**
* @test
* @expectedException phpstreams\exception\InvalidStreamException
Expand Down Expand Up @@ -137,6 +144,30 @@ public function testCollect()
$this->assertEquals(42, $instance->collect($collector));
}

public function testFirst()
{
$stream = new Stream([4, 5, 6, 7]);
$emptyStream = new Stream([]);

$this->assertEquals(4, $stream->first());

$this->assertEquals(null, $emptyStream->first());

$this->assertEquals('empty', $emptyStream->first('empty'));

$result = $stream->filter(function ($a) {
return $a > 10;
})->first();

$this->assertEquals(null, $result);

$result = $stream->filter(function ($a) {
return $a > 5;
})->first();

$this->assertEquals(6, $result);
}

public function testIsSortedWithSortedSource()
{
$sortedSource = $this->getMockBuilder('phpstreams\Stream')
Expand Down