Skip to content

Commit

Permalink
[5.4] Faster implementation for Arr::crossJoin() (#19864)
Browse files Browse the repository at this point in the history
* Faster implementation for Arr::crossJoin()

* Stricter tests, for the internal ordering of the resulting arrays

* Update Arr.php
  • Loading branch information
vlakoff authored and taylorotwell committed Jul 2, 2017
1 parent d29f5eb commit 73f8da3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 12 deletions.
24 changes: 17 additions & 7 deletions src/Illuminate/Support/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,23 @@ public static function collapse($array)
*/
public static function crossJoin(...$arrays)
{
return array_reduce($arrays, function ($results, $array) {
return static::collapse(array_map(function ($parent) use ($array) {
return array_map(function ($item) use ($parent) {
return array_merge($parent, [$item]);
}, $array);
}, $results));
}, [[]]);
$results = [[]];

foreach ($arrays as $index => $array) {
$append = [];

foreach ($results as $product) {
foreach ($array as $item) {
$product[$index] = $item;

$append[] = $product;
}
}

$results = $append;
}

return $results;
}

/**
Expand Down
20 changes: 15 additions & 5 deletions tests/Support/SupportArrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,25 @@ public function testCollapse()
public function testCrossJoin()
{
// Single dimension
$this->assertEquals(
$this->assertSame(
[[1, 'a'], [1, 'b'], [1, 'c']],
Arr::crossJoin([1], ['a', 'b', 'c'])
);

// Square matrix
$this->assertEquals(
$this->assertSame(
[[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']],
Arr::crossJoin([1, 2], ['a', 'b'])
);

// Rectangular matrix
$this->assertEquals(
$this->assertSame(
[[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c']],
Arr::crossJoin([1, 2], ['a', 'b', 'c'])
);

// 3D matrix
$this->assertEquals(
$this->assertSame(
[
[1, 'a', 'I'], [1, 'a', 'II'], [1, 'a', 'III'],
[1, 'b', 'I'], [1, 'b', 'II'], [1, 'b', 'III'],
Expand All @@ -68,7 +68,17 @@ public function testCrossJoin()
);

// With 1 empty dimension
$this->assertEquals([], Arr::crossJoin([1, 2], [], ['I', 'II', 'III']));
$this->assertSame([], Arr::crossJoin([], ['a', 'b'], ['I', 'II', 'III']));
$this->assertSame([], Arr::crossJoin([1, 2], [], ['I', 'II', 'III']));
$this->assertSame([], Arr::crossJoin([1, 2], ['a', 'b'], []));

// With empty arrays
$this->assertSame([], Arr::crossJoin([], [], []));
$this->assertSame([], Arr::crossJoin([], []));
$this->assertSame([], Arr::crossJoin([]));

// Not really a proper usage, still, test for preserving BC
$this->assertSame([[]], Arr::crossJoin());
}

public function testDivide()
Expand Down

0 comments on commit 73f8da3

Please sign in to comment.