Skip to content

Commit d218435

Browse files
authored
Rearrange equal array items, pt. 2 (#37)
1 parent 2dd7b5b commit d218435

File tree

3 files changed

+205
-11
lines changed

3 files changed

+205
-11
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [3.8.1] - 2020-09-25
8+
9+
### Fixed
10+
- Rearrangement of equal array items is corrupting data by redundant replaces.
11+
712
## [3.8.0] - 2020-09-25
813

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

53-
[3.7.6]: https://github.com/swaggest/json-diff/compare/v3.7.5...v3.7.6
58+
[3.8.1]: https://github.com/swaggest/json-diff/compare/v3.8.0...v3.8.1
59+
[3.8.0]: https://github.com/swaggest/json-diff/compare/v3.7.5...v3.8.0
5460
[3.7.5]: https://github.com/swaggest/json-diff/compare/v3.7.4...v3.7.5
5561
[3.7.4]: https://github.com/swaggest/json-diff/compare/v3.7.3...v3.7.4
5662
[3.7.3]: https://github.com/swaggest/json-diff/compare/v3.7.2...v3.7.3

src/JsonDiff.php

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -503,26 +503,40 @@ private function rearrangeEqualItems(array $original, array $new)
503503

504504
$origIdx = [];
505505
foreach ($original as $i => $item) {
506-
$origIdx[$i] = $this->jsonHashOriginal->xorHash($item);
506+
$hash = $this->jsonHashOriginal->xorHash($item);
507+
$origIdx[$hash][] = $i;
507508
}
508509

509510
$newIdx = [];
510511
foreach ($new as $i => $item) {
511512
$hash = $this->jsonHashNew->xorHash($item);
512-
$newIdx[$hash][] = $i;
513+
$newIdx[$i] = $hash;
513514
}
514515

515-
$rearranged = $new;
516-
foreach ($origIdx as $i => $hash) {
517-
if (empty($newIdx[$hash])) {
518-
continue;
516+
$newRearranged = [];
517+
$changedItems = [];
518+
foreach ($newIdx as $i => $hash) {
519+
if (!empty($origIdx[$hash])) {
520+
$j = array_shift($origIdx[$hash]);
521+
522+
$newRearranged[$j] = $new[$i];
523+
} else {
524+
$changedItems []= $new[$i];
519525
}
520526

521-
$j = array_shift($newIdx[$hash]);
522-
$rearranged[$i] = $new[$j];
523-
$rearranged[$j] = $new[$i];
524527
}
525528

526-
return $rearranged;
529+
$idx = 0;
530+
foreach ($changedItems as $item) {
531+
while (array_key_exists($idx, $newRearranged)) {
532+
$idx++;
533+
}
534+
$newRearranged[$idx] = $item;
535+
}
536+
537+
ksort($newRearranged);
538+
$newRearranged = array_values($newRearranged);
539+
540+
return $newRearranged;
527541
}
528542
}

tests/src/RearrangeArrayTest.php

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,178 @@ public function testExample()
210210
$this->assertEquals('[{"value":165,"op":"test","path":"/2/height"},{"value":168,"op":"replace","path":"/2/height"}]',
211211
json_encode($diff->getPatch(), JSON_UNESCAPED_SLASHES));
212212
}
213+
214+
public function testReplacement()
215+
{
216+
$ex1 = json_decode(<<<'JSON'
217+
{
218+
"attribute": {
219+
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
220+
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
221+
"dimension": ".UpwardPropagation - Prescriptions",
222+
"object": "Patients"
223+
},
224+
"selectedStates": [
225+
"]200,500]",
226+
"]500,1000]",
227+
"]20,50]",
228+
"]100,200]",
229+
"]5000,10000]",
230+
"]5,10]",
231+
"]1,2]",
232+
"]10,20]",
233+
"null",
234+
"]10000,oo[",
235+
"]2,5]",
236+
"]0,1]",
237+
"]1000,2000]",
238+
"]50,100]",
239+
"]2000,5000]"
240+
]
241+
}
242+
JSON
243+
);
244+
245+
$ex2 = json_decode(<<<'JSON'
246+
{
247+
"attribute": {
248+
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
249+
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
250+
"dimension": ".UpwardPropagation - Prescriptions",
251+
"object": "Patients"
252+
},
253+
"selectedStates": [
254+
"]2000,5000]",
255+
"]2,5]",
256+
"]20,50]",
257+
"]1,2]",
258+
"]10000,oo[",
259+
"]200,500]",
260+
"]50,100]",
261+
"]500,1000]",
262+
"]5,10]",
263+
"]10,20]",
264+
"null",
265+
"]0,1]",
266+
"]1000,2000]",
267+
"]5000,10000]",
268+
"]100,200]"
269+
]
270+
}
271+
JSON
272+
);
273+
274+
$diff = new JsonDiff($ex1, $ex2, JsonDiff::REARRANGE_ARRAYS);
275+
$ex2r = $diff->getRearranged();
276+
$missingItems = [];
277+
foreach ($ex2->selectedStates as $i => $item) {
278+
if (!in_array($item, $ex2r->selectedStates)) {
279+
$missingItems[$i] = $item;
280+
}
281+
}
282+
283+
$this->assertEmpty($missingItems, json_encode($ex2r, JSON_UNESCAPED_SLASHES));
284+
$this->assertEquals(
285+
json_encode($ex1, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT),
286+
json_encode($ex2r, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT)
287+
);
288+
}
289+
290+
public function testReplacementChanges()
291+
{
292+
$ex1 = json_decode(<<<'JSON'
293+
{
294+
"attribute": {
295+
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
296+
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
297+
"dimension": ".UpwardPropagation - Prescriptions",
298+
"object": "Patients"
299+
},
300+
"selectedStates": [
301+
"]200,500]",
302+
"]500,1000]",
303+
"]100,200]",
304+
"]5000,10000]",
305+
"]5,10]",
306+
"]1,2]",
307+
"]10,20]",
308+
"null",
309+
"]10000,oo[",
310+
"]2,5]",
311+
"]0,1]",
312+
"]1000,2000]",
313+
"]50,100]",
314+
"]2000,5000]"
315+
]
316+
}
317+
JSON
318+
);
319+
320+
$ex2 = json_decode(<<<'JSON'
321+
{
322+
"attribute": {
323+
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
324+
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
325+
"dimension": ".UpwardPropagation - Prescriptions",
326+
"object": "Patients"
327+
},
328+
"selectedStates": [
329+
"]2000,5000]",
330+
"]2,5]",
331+
"]20,50]",
332+
"]1,2]",
333+
"]10000,oo[",
334+
"]200,500]",
335+
"]50,100]",
336+
"]500,1000]",
337+
"]5,10]",
338+
"]10,20]",
339+
"]0,1]",
340+
"]1000,2000]",
341+
"]5000,10000]",
342+
"]100,200]"
343+
]
344+
}
345+
JSON
346+
);
347+
348+
$diff = new JsonDiff($ex1, $ex2, JsonDiff::REARRANGE_ARRAYS);
349+
$ex2r = $diff->getRearranged();
350+
$missingItems = [];
351+
foreach ($ex2->selectedStates as $i => $item) {
352+
if (!in_array($item, $ex2r->selectedStates)) {
353+
$missingItems[$i] = $item;
354+
}
355+
}
356+
357+
$this->assertEmpty($missingItems, json_encode($ex2r, JSON_UNESCAPED_SLASHES));
358+
$this->assertEquals(
359+
'{
360+
"attribute": {
361+
"name": ".UpwardPropagation - Prescriptions - Log-Ranges",
362+
"attribute": ".UpwardPropagation - Prescriptions - Log-Ranges",
363+
"dimension": ".UpwardPropagation - Prescriptions",
364+
"object": "Patients"
365+
},
366+
"selectedStates": [
367+
"]200,500]",
368+
"]500,1000]",
369+
"]100,200]",
370+
"]5000,10000]",
371+
"]5,10]",
372+
"]1,2]",
373+
"]10,20]",
374+
"]20,50]",
375+
"]10000,oo[",
376+
"]2,5]",
377+
"]0,1]",
378+
"]1000,2000]",
379+
"]50,100]",
380+
"]2000,5000]"
381+
]
382+
}',
383+
json_encode($ex2r, JSON_UNESCAPED_SLASHES+JSON_PRETTY_PRINT)
384+
);
385+
}
386+
213387
}

0 commit comments

Comments
 (0)