Skip to content

Commit 7c058d5

Browse files
authored
Merge pull request #149 from martinsik/2.x
Cherry picked distinct() optimization for 2.x
2 parents f46805d + e25e575 commit 7c058d5

File tree

2 files changed

+51
-10
lines changed

2 files changed

+51
-10
lines changed

src/Operator/DistinctOperator.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,8 @@ final class DistinctOperator implements OperatorInterface
2222

2323
public function __construct(callable $keySelector = null, callable $comparer = null)
2424
{
25-
26-
$this->comparer = $comparer ?: function ($x, $y) {
27-
return $x == $y;
28-
};
29-
25+
$this->comparer = $comparer;
3026
$this->keySelector = $keySelector;
31-
3227
}
3328

3429
public function __invoke(ObservableInterface $observable, ObserverInterface $observer): DisposableInterface
@@ -41,15 +36,22 @@ function ($value) use ($observer, &$values) {
4136
try {
4237
$key = $this->keySelector ? ($this->keySelector)($value) : $value;
4338

44-
foreach ($values as $v) {
45-
$comparerEquals = ($this->comparer)($key, $v);
39+
if ($this->comparer) {
40+
foreach ($values as $v) {
41+
$comparerEquals = call_user_func($this->comparer, $key, $v);
4642

47-
if ($comparerEquals) {
43+
if ($comparerEquals) {
44+
return;
45+
}
46+
}
47+
$values[] = $key;
48+
} else {
49+
if (array_key_exists($key, $values)) {
4850
return;
4951
}
52+
$values[$key] = null;
5053
}
5154

52-
$values[] = $key;
5355
$observer->onNext($value);
5456

5557
} catch (\Throwable $e) {

test/Rx/Functional/Operator/DistinctTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,45 @@ public function distinct_CustomKey_some_throw()
355355

356356
}
357357

358+
/**
359+
* @test
360+
*/
361+
public function distinct_CustomKey_and_CustomComparer_some_duplicates()
362+
{
363+
364+
$xs = $this->createHotObservable([
365+
onNext(280, ['id' => 4]),
366+
onNext(300, ['id' => 2]),
367+
onNext(350, ['id' => 12]),
368+
onNext(380, ['id' => 3]),
369+
onNext(400, ['id' => 24]),
370+
onCompleted(420)
371+
]);
372+
373+
$results = $this->scheduler->startWithCreate(function () use ($xs) {
374+
return $xs->distinctKey(
375+
function ($x) {
376+
return $x['id'];
377+
},
378+
$this->modComparer(10)
379+
)->map(function ($x) {
380+
return $x['id'];
381+
});
382+
});
383+
384+
$this->assertMessages([
385+
onNext(280, 4),
386+
onNext(300, 2),
387+
onNext(380, 3),
388+
onCompleted(420)
389+
], $results->getMessages());
390+
391+
$this->assertSubscriptions([
392+
subscribe(200, 420)
393+
], $xs->getSubscriptions());
394+
395+
}
396+
358397

359398
public function modComparer($mod)
360399
{

0 commit comments

Comments
 (0)