raigu / ordered-lists-sync
用于通过最小插入和删除操作同步有序数据的库。
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^9.5
README
用于通过最小插入和删除操作同步有序数据的库。
适用于大型数据集。适合与外部源同步内部数据。见演示。
兼容性
- PHP 7.4, 8.0, 8.1, 8.2, 8.3
安装
$ composer require raigu/ordered-lists-sync
使用
\Raigu\OrderedListsSynchronization\Synchronization
比较源列表和目标列表。它检测源相对于目标中添加或删除的元素,并调用相应的回调。
源和目标必须是Iterator
类型。
$synchronization = new \Raigu\OrderedListsSynchronization\Synchronization(); $synchronization( $source = new ArrayIterator(['A', 'B', 'D']), $target = new ArrayIterator(['B', 'C', 'D']), $add = function ($element) { echo "ADD: {$element}\n"; }, $remove = function ($element) { echo "REMOVE: {$element}\n"; } );
输出
ADD: A
REMOVE: C
用例
具有演示代码的示例用例
- 同步关系数据库表与另一个(演示:./demo/database_tables.php)
- 同步本地数据与互联网中可用的数据(演示:./demo/internet_to_database.php)
- 同步具有唯一ID和多个属性的实体(演示:./demo/sync_entities.php)
设计
\Raigu\OrderedListsSynchronization\Synchronization
只有一个目的。因此,它被设计成一个函数实例,不暴露任何方法。它是一个对象,因为它允许在将来扩展它(例如添加日志)。
使用Iterator
类型作为源和目标有几个优点。
首先,您可以创建自己的迭代器作为独立的组件,这更容易开发和测试。
其次,可以解决更复杂的问题。特别是在存在内存限制的情况下。
您可以创建源或目标作为生成器,实现Iterate或IteratorAggregate接口,或使用标准PHP库(SPL)迭代器。
第三,它允许创建在构造函数中不做任何工作的组件。这在使用依赖注入或声明式编程时很方便。
开发
设置
$ git clone git@github.com:raigu/ordered-lists-sync.git
$ cd ordered-lists-sync
$ composer install
测试
$ composer test
$ composer coverage
算法
算法的工作方式类似于我们使用字典。如果所有单词都是有序的,那么我们就知道某个单词应该在哪里。如果我们有两个字典,并从开头逐个单词比较它们,那么我们可以检测到添加或删除的单词。
示例(V
表示迭代器的当前位置)
V
Source: A, B, D
V
Target: B, C, D
A < B => 如果源在目标之前,这意味着目标中缺少值。如果目标中有一个A,那么它应该在B之前。但它不在那里。因此,它是缺失的,应该被添加。添加A并移动源光标
V
Source: A, B, D
V
Target: B, C, D
B = B => 如果源和目标相等,则它们已同步。移动两个光标。
V
Source: A, B, D
V
Target: B, C, D
D > C => 如果源在目标之后,这意味着源中已经从源中删除了值。因此,删除C并将光标向前移动
V
Source: A, B, D
V
Target: B, C, D
D = D => 它们已经同步。移动两个光标。