Skip to content

Commit

Permalink
Rearrange equal array items, pt. 2 (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
vearutop authored Sep 25, 2020
1 parent 2dd7b5b commit d218435
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 11 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.8.1] - 2020-09-25

### Fixed
- Rearrangement of equal array items is corrupting data by redundant replaces.

## [3.8.0] - 2020-09-25

### Added
Expand Down Expand Up @@ -50,7 +55,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Compatibility option to `TOLERATE_ASSOCIATIVE_ARRAYS` that mimic JSON objects.

[3.7.6]: https://github.com/swaggest/json-diff/compare/v3.7.5...v3.7.6
[3.8.1]: https://github.com/swaggest/json-diff/compare/v3.8.0...v3.8.1
[3.8.0]: https://github.com/swaggest/json-diff/compare/v3.7.5...v3.8.0
[3.7.5]: https://github.com/swaggest/json-diff/compare/v3.7.4...v3.7.5
[3.7.4]: https://github.com/swaggest/json-diff/compare/v3.7.3...v3.7.4
[3.7.3]: https://github.com/swaggest/json-diff/compare/v3.7.2...v3.7.3
Expand Down
34 changes: 24 additions & 10 deletions src/JsonDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,26 +503,40 @@ private function rearrangeEqualItems(array $original, array $new)

$origIdx = [];
foreach ($original as $i => $item) {
$origIdx[$i] = $this->jsonHashOriginal->xorHash($item);
$hash = $this->jsonHashOriginal->xorHash($item);
$origIdx[$hash][] = $i;
}

$newIdx = [];
foreach ($new as $i => $item) {
$hash = $this->jsonHashNew->xorHash($item);
$newIdx[$hash][] = $i;
$newIdx[$i] = $hash;
}

$rearranged = $new;
foreach ($origIdx as $i => $hash) {
if (empty($newIdx[$hash])) {
continue;
$newRearranged = [];
$changedItems = [];
foreach ($newIdx as $i => $hash) {
if (!empty($origIdx[$hash])) {
$j = array_shift($origIdx[$hash]);

$newRearranged[$j] = $new[$i];
} else {
$changedItems []= $new[$i];
}

$j = array_shift($newIdx[$hash]);
$rearranged[$i] = $new[$j];
$rearranged[$j] = $new[$i];
}

return $rearranged;
$idx = 0;
foreach ($changedItems as $item) {
while (array_key_exists($idx, $newRearranged)) {
$idx++;
}
$newRearranged[$idx] = $item;
}

ksort($newRearranged);
$newRearranged = array_values($newRearranged);

return $newRearranged;
}
}
174 changes: 174 additions & 0 deletions tests/src/RearrangeArrayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,178 @@ public function testExample()
$this->assertEquals('[{"value":165,"op":"test","path":"/2/height"},{"value":168,"op":"replace","path":"/2/height"}]',
json_encode($diff->getPatch(), JSON_UNESCAPED_SLASHES));
}

public function testReplacement()
{
$ex1 = json_decode(<<<'JSON'
{
"attribute": {
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
"dimension": ".UpwardPropagation - Prescriptions",
"object": "Patients"
},
"selectedStates": [
"]200,500]",
"]500,1000]",
"]20,50]",
"]100,200]",
"]5000,10000]",
"]5,10]",
"]1,2]",
"]10,20]",
"null",
"]10000,oo[",
"]2,5]",
"]0,1]",
"]1000,2000]",
"]50,100]",
"]2000,5000]"
]
}
JSON
);

$ex2 = json_decode(<<<'JSON'
{
"attribute": {
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
"dimension": ".UpwardPropagation - Prescriptions",
"object": "Patients"
},
"selectedStates": [
"]2000,5000]",
"]2,5]",
"]20,50]",
"]1,2]",
"]10000,oo[",
"]200,500]",
"]50,100]",
"]500,1000]",
"]5,10]",
"]10,20]",
"null",
"]0,1]",
"]1000,2000]",
"]5000,10000]",
"]100,200]"
]
}
JSON
);

$diff = new JsonDiff($ex1, $ex2, JsonDiff::REARRANGE_ARRAYS);
$ex2r = $diff->getRearranged();
$missingItems = [];
foreach ($ex2->selectedStates as $i => $item) {
if (!in_array($item, $ex2r->selectedStates)) {
$missingItems[$i] = $item;
}
}

$this->assertEmpty($missingItems, json_encode($ex2r, JSON_UNESCAPED_SLASHES));
$this->assertEquals(
json_encode($ex1, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT),
json_encode($ex2r, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT)
);
}

public function testReplacementChanges()
{
$ex1 = json_decode(<<<'JSON'
{
"attribute": {
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
"dimension": ".UpwardPropagation - Prescriptions",
"object": "Patients"
},
"selectedStates": [
"]200,500]",
"]500,1000]",
"]100,200]",
"]5000,10000]",
"]5,10]",
"]1,2]",
"]10,20]",
"null",
"]10000,oo[",
"]2,5]",
"]0,1]",
"]1000,2000]",
"]50,100]",
"]2000,5000]"
]
}
JSON
);

$ex2 = json_decode(<<<'JSON'
{
"attribute": {
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
"dimension": ".UpwardPropagation - Prescriptions",
"object": "Patients"
},
"selectedStates": [
"]2000,5000]",
"]2,5]",
"]20,50]",
"]1,2]",
"]10000,oo[",
"]200,500]",
"]50,100]",
"]500,1000]",
"]5,10]",
"]10,20]",
"]0,1]",
"]1000,2000]",
"]5000,10000]",
"]100,200]"
]
}
JSON
);

$diff = new JsonDiff($ex1, $ex2, JsonDiff::REARRANGE_ARRAYS);
$ex2r = $diff->getRearranged();
$missingItems = [];
foreach ($ex2->selectedStates as $i => $item) {
if (!in_array($item, $ex2r->selectedStates)) {
$missingItems[$i] = $item;
}
}

$this->assertEmpty($missingItems, json_encode($ex2r, JSON_UNESCAPED_SLASHES));
$this->assertEquals(
'{
"attribute": {
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
"dimension": ".UpwardPropagation - Prescriptions",
"object": "Patients"
},
"selectedStates": [
"]200,500]",
"]500,1000]",
"]100,200]",
"]5000,10000]",
"]5,10]",
"]1,2]",
"]10,20]",
"]20,50]",
"]10000,oo[",
"]2,5]",
"]0,1]",
"]1000,2000]",
"]50,100]",
"]2000,5000]"
]
}',
json_encode($ex2r, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT)
);
}

}

0 comments on commit d218435

Please sign in to comment.