jwadhams/merge-a-trois

PHP数组数据的三向合并

2.0.0 2023-02-20 20:45 UTC

This package is auto-updated.

Last update: 2024-09-21 00:34:31 UTC


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移植过来的。