{"id":19742900,"url":"https://github.com/jeanplevesque/collectiontracking","last_synced_at":"2026-05-16T22:32:52.154Z","repository":{"id":144386493,"uuid":"489464704","full_name":"jeanplevesque/CollectionTracking","owner":"jeanplevesque","description":"Get the [Insert, Delete, Move, Replace] operations to apply on collection A to obtain collection B.","archived":false,"fork":false,"pushed_at":"2023-07-11T12:22:17.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-05T16:41:42.491Z","etag":null,"topics":["collection","csharp","diffing","dotnet"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeanplevesque.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-06T19:01:43.000Z","updated_at":"2022-08-24T19:50:55.000Z","dependencies_parsed_at":"2024-11-12T01:34:29.316Z","dependency_job_id":"4afd8e4f-6226-4c58-8691-4de2d36c1cf9","html_url":"https://github.com/jeanplevesque/CollectionTracking","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jeanplevesque/CollectionTracking","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeanplevesque%2FCollectionTracking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeanplevesque%2FCollectionTracking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeanplevesque%2FCollectionTracking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeanplevesque%2FCollectionTracking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeanplevesque","download_url":"https://codeload.github.com/jeanplevesque/CollectionTracking/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeanplevesque%2FCollectionTracking/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265262539,"owners_count":23736411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["collection","csharp","diffing","dotnet"],"created_at":"2024-11-12T01:34:18.526Z","updated_at":"2026-05-16T22:32:52.112Z","avatar_url":"https://github.com/jeanplevesque.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CollectionTracking\r\n\r\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square)](LICENSE) ![Version](https://img.shields.io/nuget/v/CollectionTracking?style=flat-square) ![Downloads](https://img.shields.io/nuget/dt/CollectionTracking?style=flat-square)\r\n\r\n## Goal\r\nThis package was developed to interpret a series of immutable lists (from a business layer) as one mutable lists (in a presentation layer).\r\nIn other words, convert `IObservable\u003cIEnumerable\u003cT\u003e\u003e` to `ObservableCollection\u003cT\u003e`.\r\n\r\n## Usage\r\n\r\n### 1. Get the differences\r\nUse `CollectionTracker.GetOperations` to compare 2 enumerables.\r\n\r\n```csharp\r\nusing CollectionTracking;\r\n\r\n// (...)\r\n\r\nvar source = new[] { \"B\", \"C\", \"A\" };\r\nvar target = new[] { \"A\", \"B\", \"C\", \"D\" };\r\n\r\nvar operations = CollectionTracker.GetOperations(source, target);\r\n\r\nforeach (var operation in operations)\r\n{\r\n\tConsole.WriteLine(operation);\r\n}\r\n```\r\n\r\nThis code prints the following.\r\n```\r\nMove 'A' from [2] to [0]\r\nInsert 'D' at [3]\r\n```\r\n\r\n### 2. Use the differences to modify an `IList`\r\n\r\nUse `CollectionTracker.ApplyOperations` to apply a series of `CollectionOperation`s on an `IList`.\r\n\r\n```csharp\r\nvar list = source.ToList();\r\nlist.ApplyOperations(operations);\r\n```\r\n\r\nThis code initializes the `list` variable with the content being [BCA].\r\nThe `ApplyOperations` modifies that `list` so that it becomes [ABCD].\r\nThis is very useful when manipulating an `ObservableCollection` bound to a UI component (such as `ItemsControl.ItemsSource`).\r\n\r\n# CollectionTracking.DynamicData\r\n\r\n## Goal\r\nExpose conversion methods to relevant types from the [DynamicData library](https://github.com/reactivemarbles/DynamicData).\r\n\r\n## Usage\r\n\r\n```csharp\r\nusing CollectionTracking;\r\nusing DynamicData;\r\n\r\n// (...)\r\n\r\nvar source = new[] { \"B\", \"C\", \"A\" };\r\nvar target = new[] { \"A\", \"B\", \"C\", \"D\" };\r\n\r\nvar operations = CollectionTracker.GetOperations(source, target);\r\n\r\n// Convert all changes.\r\nIChangeSet\u003cstring\u003e changeSet = operations.ToChangeSet();\r\n\r\n// Convert a single change.\r\nChange\u003cstring\u003e change = operations[0].ToChange();\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeanplevesque%2Fcollectiontracking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeanplevesque%2Fcollectiontracking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeanplevesque%2Fcollectiontracking/lists"}