jwadhams/ merge-a-trois
PHP数组数据的三向合并
Requires
- php: >=8.1
Requires (Dev)
- phpunit/phpunit: ^10
README
我有一个后端为PHP的应用程序,为JavaScript客户端提供大量的JSON编码的未结构化数据块。客户端在大型对象内部操作数据,然后可能几分钟后再将整个修改后的对象返回到后端。
可能有两个人在几乎同步地进行协作,共同处理同一个大型对象(通常是在大型对象的不同部分),因此后端需要一种合并这些更改的方法。
该库的目标是静默地合并更改,并最终获得一个权威的服务器存储对象,尽可能地尊重所有协作者。与软件版本控制合并不同,没有用户可以仲裁冲突,因此算法总是返回一个答案,我们将审计跟踪保留在此库之外。
在疑问时,最新的更改获胜。
为什么是三向合并?
每个客户端首先拉取一个已知良好的对象版本。三向合并技术允许我们使用潜在冲突更改的公共祖先,并在发现已删除的内容时特别有用。
示例
这是一个基本合并示例,其中公共祖先是空白,两个后代都进行了非冲突的添加更改
$a = $b = $original = []; $a['a'] = 'apple'; $b['b'] = 'banana'; JWadhams\MergeATrois::merge($original, $a, $b); //['a'=>'apple', 'b'=>'banana']
如果两个子代都进行了冲突更改,则第二个更改获胜。
$a = $b = $original = []; $a['a'] = 'apple'; $b['a'] = 'avocado'; JWadhams\MergeATrois::merge($original, $a, $b); //['a'=>'avocado']
复杂关联数组内的更改是递归合并的。
$a = $b = $original = [ 'person' => ['first_name' => 'Marge', 'last_name' => 'Bouvier'], 'hobby' => ['type' => 'bowling', 'rank' => 'novice'], ]; $a['person']['last_name'] = 'Simpson'; $b['hobby']['rank'] = 'champion'; JWadhams\MergeATrois::merge($original, $a, $b); /*[ "person" => [ "first_name" => "Marge", "last_name" => "Simpson", ], "hobby" => [ "type" => "bowling", "rank" => "champion", ], ]*/
在合并数字数组时,算法寻找唯一的内容,并忽略键。在这里,a和b都在索引0处引入了新内容,算法保留了这两个贡献。
$a = $b = $original = []; $a[] = 'apple'; $b[] = 'banana'; JWadhams\MergeATrois::merge($original, $a, $b); //['apple', 'banana']
在这个例子中,算法内部将字符串'apple'视为已删除,并添加了新的字符串'APPLE'。
$a = $b = $original = ['apple']; $a[0] = 'APPLE'; $b[] = 'banana'; JWadhams\MergeATrois::merge($original, $a, $b); //['APPLE', 'banana']
此库的一个基本规则是,在疑问时,最新的更改获胜。因此,返回的数字数组将遵循B的顺序,然后追加A的新内容。
在这个例子中,我们在B前面添加内容,合并结果遵循B的顺序。
$a = $b = $original = ['apple']; array_unshift($b, 'banana'); // $b now equals ['banana', 'apple'] JWadhams\MergeATrois::merge($original, $a, $b); //['banana', 'apple']
在这个例子中,内容被添加到A中。合并结果遵循B的顺序,除了注意到A的删除。然后合并追加A中B不知道的新内容。
$a = $b = $original = ['zucchini']; unset($a[0]); //$a equals [] array_unshift($a, 'apple'); //$a equals ['apple'] array_unshift($b, 'banana'); //$b equals ['banana', 'zucchini'] JWadhams\MergeATrois::merge($original, $a, $b); //['banana', 'apple']
注意合并算法将决定PHP json_encode
方法来决定什么是一个数字数组:如果json_encode
使用JSON的[]
表示法,我们将数组视为键无关紧要。如果你的数组被编码为{}
,它将被处理为关联数组,并且索引将被保留。
(json_encode
似乎在寻找具有无间隔的顺序数字零索引键的JSON表示法。)
$a = $b = $original = [2 => 'banana', 26 => 'zucchini']; JWadhams\MergeATrois::merge($original, $a, $b); //[2 => 'banana', 26 => 'zucchini']
安装
安装此库的最佳方式是通过Composer
composer require jwadhams/merge-a-trois
如果这不适合您,并且您想自己管理更新,则整个库都包含在src/JWadhams/MergeATrois.php
中,您可以根据需要将其下载到您的项目中。
curl -O https://raw.githubusercontent.com/jwadhams/merge-a-trois/master/src/JWadhams/MergeATrois.php
特别感谢
感谢Lukas Benes — 此库最初是从您的出色的CoffeeScript库3-way-merge移植过来的。