list_diff 1.1.3

  • Readme
  • Changelog
  • Example
  • Installing
  • 68

Offers a diff method that accepts two Lists and returns a list of Operations for turning the first list into the second one:

var operations = await diff(
  ['coconut', 'nut', 'peanut'],
  ['kiwi', 'coconut', 'maracuja', 'nut', 'banana'],
);
operations.forEach(print);

// Operations:
// Insertion of kiwi at 0.
// Insertion of maracuja at 2.
// Insertion of banana at 4.
// Deletion of peanut at 5.

Operations are either an insertion or deletion of an item at an index. You can also directly apply them to a list:

// Let's try it out!
var fruitBowl = ['coconut', 'nut', 'peanut'];

for (var operation in operations) {
    operation.applyTo(fruitBowl);
}

// Transforming:
// [coconut, nut, peanut]
// [kiwi, coconut, nut, peanut]
// [kiwi, coconut, maracuja, nut, peanut]
// [kiwi, coconut, maracuja, nut, banana, peanut]
// [kiwi, coconut, maracuja, nut, banana]

The lists' items are compared using their == operator.

A word about performance and threading #

The current version of the function is not as performant as it could be. The runtime is currently O(N*M), where N and M are the lengths of the lists.

If the data sets are large, the diff function automatically spawns an isolate. If you don't want more control on whether an isolate should be spawned, you can also explicitly set the [spawnIsolate] parameter:

var operations = await diff(first, second, spawnIsolate: true);

For Flutter users #

[diff] can be used to calculate updates for an [AnimatedList]:

final _listKey = GlobalKey<AnimatedListState>();
List<String> _lastFruits;
...
StreamBuilder<String>(
  stream: fruitStream,
  initialData: [],
  builder: (context, snapshot) {
    for (var operation in await diff(_lastFruits, snapshot.data)) {
      if (operation.isInsertion) {
        _listKey.insertItem(operation.index);
      } else {
        _listKey.removeItem(operation.index, (context, animation) => ...);
      }
    }
    return AnimatedList(
      key: _listKey,
      itemBuilder: (context, index, animation) => ...,
    );
  },
),

[1.1.3] - 2019-10-14

  • Important fix: Fixed error in algorithm that made it crash when the two lists are the same.

[1.1.2] - 2019-10-13

  • Important fix: Fixed error in algorithm that produced wrong results that couldn't actually be applied.

[1.1.1] - 2019-10-10

  • BREAKING CHANGE: runOnSeparateIsolate renamed to spawnIsolate.
  • By default, the diff function intelligently tries to choose whether or not to spawn an isolate based on the lengths on the lists.
  • Revised readme.

[1.1.0] - 2019-10-09

  • BREAKING CHANGE: diff is now asynchronous.
  • Add support for running diff on another isolate by simply setting runOnSeparateIsolate to true.
  • Add isolated.dart example.
  • Better error messages.
  • Revised doc comments.
  • Add readme.

[1.1.0] - 2019-10-09

  • BREAKING CHANGE: diff is now asynchronous.
  • Add support for running diff on another isolate by simply setting runOnSeparateIsolate to true.
  • Add isolated.dart example.
  • Better error messages.
  • Revised doc comments.
  • Add readme.

[1.0.1] - 2019-10-09

  • Remove unused dependency dart:isolate.

[1.0.0] - 2019-10-09

  • Initial release featuring the diff function that takes two lists and returns a list of Operations that turn the first into the second list if applied in order.

example/main.dart

import 'package:list_diff/list_diff.dart';

void main() async {
  //var nutMix = ['coconut', 'nut', 'peanut'];
  //var tropic = ['kiwi', 'coconut', 'maracuja', 'nut', 'banana'];
  var nutMix = [1, 2, 3];
  var tropic = [1, 2, 3];

  // Now, let's turn the nut mix into the tropical mix.
  var recipe = await diff(nutMix, tropic);

  // Let's try it out!
  var bowl = List<int>.from(nutMix);
  print(bowl);

  for (var operation in recipe) {
    operation.applyTo(bowl);
    print('$operation\n$bowl');
  }

  // Output:
  // [coconut, nut, peanut]
  // Insertion of kiwi at 0.
  // [kiwi, coconut, nut, peanut]
  // Insertion of maracuja at 2.
  // [kiwi, coconut, maracuja, nut, peanut]
  // Insertion of banana at 4.
  // [kiwi, coconut, maracuja, nut, banana, peanut]
  // Deletion of peanut at 5.
  // [kiwi, coconut, maracuja, nut, banana]
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  list_diff: ^1.1.3

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:list_diff/list_diff.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
36
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
68
Learn more about scoring.

We analyzed this package on Nov 7, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.6.0
  • pana: 0.12.21

Platforms

Detected platforms: Flutter, other

Primary library: package:list_diff/list_diff.dart with components: isolate.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.2 <3.0.0
async >=2.2.0 <2.5.0 2.4.0
Transitive dependencies
collection 1.14.12