Ecng.StringSearch
1.0.220
dotnet add package Ecng.StringSearch --version 1.0.220
NuGet\Install-Package Ecng.StringSearch -Version 1.0.220
<PackageReference Include="Ecng.StringSearch" Version="1.0.220" />
<PackageVersion Include="Ecng.StringSearch" Version="1.0.220" />
<PackageReference Include="Ecng.StringSearch" />
paket add Ecng.StringSearch --version 1.0.220
#r "nuget: Ecng.StringSearch, 1.0.220"
#:package Ecng.StringSearch@1.0.220
#addin nuget:?package=Ecng.StringSearch&version=1.0.220
#tool nuget:?package=Ecng.StringSearch&version=1.0.220
StringSearch - Efficient String Search Data Structures
A collection of high-performance string search data structures including Trie, Patricia Trie, and Ukkonen's Suffix Tree implementations. These data structures are optimized for fast prefix and substring searching operations.
Features
- Multiple trie implementations for different use cases
- Fast prefix and substring searching
- Generic value associations with string keys
- Memory-efficient Patricia Trie (compressed trie)
- Ukkonen's Suffix Tree for advanced substring searching
- Concurrent trie support for multi-threaded scenarios
- MIT licensed open-source implementation
Installation
Add a reference to the StringSearch project in your solution.
Quick Start
Basic Trie Usage
using Gma.DataStructures.StringSearch;
// Create a Patricia Trie (most commonly used)
var trie = new PatriciaTrie<int>();
// Add key-value pairs
trie.Add("apple", 1);
trie.Add("application", 2);
trie.Add("apply", 3);
trie.Add("banana", 4);
// Retrieve values by prefix
var results = trie.Retrieve("app");
// Returns: [1, 2, 3] (values associated with "apple", "application", "apply")
var results2 = trie.Retrieve("ban");
// Returns: [4] (value associated with "banana")
Data Structures
PatriciaTrie
A space-optimized trie (radix tree) that stores strings efficiently by compressing chains of nodes with single children.
Best for:
- Prefix searching
- Autocomplete features
- Memory-efficient storage of strings with common prefixes
using Gma.DataStructures.StringSearch;
var trie = new PatriciaTrie<string>();
// Add entries
trie.Add("test", "Test Value");
trie.Add("testing", "Testing Value");
trie.Add("tester", "Tester Value");
trie.Add("tea", "Tea Value");
// Search by prefix
var results = trie.Retrieve("test");
// Returns: ["Test Value", "Testing Value", "Tester Value"]
var results2 = trie.Retrieve("te");
// Returns: ["Test Value", "Testing Value", "Tester Value", "Tea Value"]
PatriciaSuffixTrie
A Patricia Trie that indexes all suffixes of added strings, enabling substring searching.
Best for:
- Substring searching
- Finding all occurrences of a pattern within stored strings
- "Contains" queries
using Gma.DataStructures.StringSearch;
// Create with minimum query length of 3 characters
var suffixTrie = new PatriciaSuffixTrie<string>(minQueryLength: 3);
// Add strings with associated values
suffixTrie.Add("hello world", "Document 1");
suffixTrie.Add("world peace", "Document 2");
suffixTrie.Add("hello there", "Document 3");
// Search for substring "wor"
var results = suffixTrie.Retrieve("wor");
// Returns: ["Document 1", "Document 2"] (both contain "world")
// Search for substring "hello"
var results2 = suffixTrie.Retrieve("hello");
// Returns: ["Document 1", "Document 3"]
SuffixTrie
A standard trie-based suffix tree implementation.
using Gma.DataStructures.StringSearch;
// Create with minimum suffix length of 2
var suffixTrie = new SuffixTrie<string>(minSuffixLength: 2);
suffixTrie.Add("programming", "Item 1");
suffixTrie.Add("grammar", "Item 2");
// Search for "gram"
var results = suffixTrie.Retrieve("gram");
// Returns: ["Item 1", "Item 2"] (both contain "gram")
UkkonenTrie
An implementation of Ukkonen's linear-time suffix tree construction algorithm.
Best for:
- Large text indexing
- Efficient substring search in big datasets
- Advanced pattern matching
using Gma.DataStructures.StringSearch;
// Create with minimum suffix length
var ukkonen = new UkkonenTrie<string>(minSuffixLength: 3);
ukkonen.Add("banana", "Fruit 1");
ukkonen.Add("bandana", "Clothing 1");
// Search for "ana"
var results = ukkonen.Retrieve("ana");
// Returns: ["Fruit 1", "Clothing 1"]
ConcurrentTrie
Thread-safe trie implementation for concurrent access scenarios.
using Gma.DataStructures.StringSearch;
using System.Threading.Tasks;
var concurrentTrie = new ConcurrentTrie<int>();
// Safe for concurrent access
Parallel.For(0, 1000, i =>
{
concurrentTrie.Add($"key{i}", i);
});
// Retrieve from multiple threads
var results = concurrentTrie.Retrieve("key1");
Common Interface: ITrie<TValue>
All trie implementations implement the ITrie<TValue> interface:
public interface ITrie<TValue>
{
void Add(string key, TValue value);
IEnumerable<TValue> Retrieve(string query);
void Remove(TValue value);
void RemoveRange(IEnumerable<TValue> values);
void Clear();
}
Usage Examples
Autocomplete System
using Gma.DataStructures.StringSearch;
public class AutocompleteSystem
{
private readonly PatriciaTrie<string> _trie;
public AutocompleteSystem()
{
_trie = new PatriciaTrie<string>();
}
public void AddWord(string word)
{
_trie.Add(word.ToLower(), word);
}
public IEnumerable<string> GetSuggestions(string prefix)
{
return _trie.Retrieve(prefix.ToLower()).Distinct();
}
}
// Usage
var autocomplete = new AutocompleteSystem();
autocomplete.AddWord("Apple");
autocomplete.AddWord("Application");
autocomplete.AddWord("Approach");
autocomplete.AddWord("Banana");
var suggestions = autocomplete.GetSuggestions("app");
// Returns: ["Apple", "Application", "Approach"]
Document Search Engine
using Gma.DataStructures.StringSearch;
using System.Linq;
public class DocumentSearchEngine
{
private readonly PatriciaSuffixTrie<string> _index;
public DocumentSearchEngine(int minQueryLength = 3)
{
_index = new PatriciaSuffixTrie<string>(minQueryLength);
}
public void IndexDocument(string documentId, string content)
{
// Index the document content
_index.Add(content.ToLower(), documentId);
}
public IEnumerable<string> Search(string query)
{
if (query.Length < 3)
return Enumerable.Empty<string>();
return _index.Retrieve(query.ToLower()).Distinct();
}
}
// Usage
var searchEngine = new DocumentSearchEngine();
searchEngine.IndexDocument("doc1", "The quick brown fox jumps over the lazy dog");
searchEngine.IndexDocument("doc2", "A quick movement in the forest");
searchEngine.IndexDocument("doc3", "The lazy cat sleeps");
var results = searchEngine.Search("quick");
// Returns: ["doc1", "doc2"]
var results2 = searchEngine.Search("lazy");
// Returns: ["doc1", "doc3"]
Phone Directory
using Gma.DataStructures.StringSearch;
public class Contact
{
public string Name { get; set; }
public string Phone { get; set; }
public override string ToString() => $"{Name}: {Phone}";
}
public class PhoneDirectory
{
private readonly PatriciaTrie<Contact> _trie;
public PhoneDirectory()
{
_trie = new PatriciaTrie<Contact>();
}
public void AddContact(string name, string phone)
{
var contact = new Contact { Name = name, Phone = phone };
_trie.Add(name.ToLower(), contact);
}
public IEnumerable<Contact> FindByPrefix(string namePrefix)
{
return _trie.Retrieve(namePrefix.ToLower());
}
public void RemoveContact(Contact contact)
{
_trie.Remove(contact);
}
public void Clear()
{
_trie.Clear();
}
}
// Usage
var directory = new PhoneDirectory();
directory.AddContact("Alice Smith", "555-0001");
directory.AddContact("Alice Johnson", "555-0002");
directory.AddContact("Bob Brown", "555-0003");
var contacts = directory.FindByPrefix("alic");
// Returns all contacts starting with "alic"
IP Address Lookup
using Gma.DataStructures.StringSearch;
public class IpAddressLookup
{
private readonly PatriciaTrie<string> _trie;
public IpAddressLookup()
{
_trie = new PatriciaTrie<string>();
}
public void AddMapping(string ipPrefix, string location)
{
_trie.Add(ipPrefix, location);
}
public IEnumerable<string> FindLocations(string ipPrefix)
{
return _trie.Retrieve(ipPrefix);
}
}
// Usage
var ipLookup = new IpAddressLookup();
ipLookup.AddMapping("192.168.1", "Local Network A");
ipLookup.AddMapping("192.168.2", "Local Network B");
ipLookup.AddMapping("10.0.0", "VPN Network");
var locations = ipLookup.FindLocations("192.168");
// Returns: ["Local Network A", "Local Network B"]
Tag Search System
using Gma.DataStructures.StringSearch;
using System.Collections.Generic;
public class TaggedItem
{
public string Id { get; set; }
public string Title { get; set; }
public List<string> Tags { get; set; }
}
public class TagSearchSystem
{
private readonly PatriciaTrie<TaggedItem> _tagIndex;
public TagSearchSystem()
{
_tagIndex = new PatriciaTrie<TaggedItem>();
}
public void AddItem(TaggedItem item)
{
foreach (var tag in item.Tags)
{
_tagIndex.Add(tag.ToLower(), item);
}
}
public IEnumerable<TaggedItem> SearchByTag(string tagPrefix)
{
return _tagIndex.Retrieve(tagPrefix.ToLower()).Distinct();
}
public void RemoveItem(TaggedItem item)
{
_tagIndex.Remove(item);
}
}
// Usage
var tagSystem = new TagSearchSystem();
tagSystem.AddItem(new TaggedItem
{
Id = "1",
Title = "Article about C#",
Tags = new List<string> { "csharp", "programming", "dotnet" }
});
tagSystem.AddItem(new TaggedItem
{
Id = "2",
Title = "Article about C++",
Tags = new List<string> { "cpp", "programming", "native" }
});
var items = tagSystem.SearchByTag("prog");
// Returns both articles (both have "programming" tag)
var csharpItems = tagSystem.SearchByTag("csh");
// Returns only the first article
Code Symbol Search
using Gma.DataStructures.StringSearch;
public class Symbol
{
public string Name { get; set; }
public string Type { get; set; } // class, method, property, etc.
public string FilePath { get; set; }
}
public class CodeSymbolIndex
{
private readonly PatriciaTrie<Symbol> _symbolTrie;
private readonly PatriciaSuffixTrie<Symbol> _substringTrie;
public CodeSymbolIndex()
{
_symbolTrie = new PatriciaTrie<Symbol>();
_substringTrie = new PatriciaSuffixTrie<Symbol>(minQueryLength: 2);
}
public void IndexSymbol(Symbol symbol)
{
var key = symbol.Name.ToLower();
_symbolTrie.Add(key, symbol);
_substringTrie.Add(key, symbol);
}
public IEnumerable<Symbol> SearchByPrefix(string prefix)
{
return _symbolTrie.Retrieve(prefix.ToLower());
}
public IEnumerable<Symbol> SearchBySubstring(string substring)
{
return _substringTrie.Retrieve(substring.ToLower());
}
}
// Usage
var codeIndex = new CodeSymbolIndex();
codeIndex.IndexSymbol(new Symbol
{
Name = "GetUserById",
Type = "method",
FilePath = "UserService.cs"
});
codeIndex.IndexSymbol(new Symbol
{
Name = "UserRepository",
Type = "class",
FilePath = "UserRepository.cs"
});
// Prefix search
var prefixResults = codeIndex.SearchByPrefix("getuser");
// Returns: GetUserById
// Substring search
var substringResults = codeIndex.SearchBySubstring("user");
// Returns: GetUserById, UserRepository
Performance Characteristics
| Data Structure | Add | Search | Space | Best Use Case |
|---|---|---|---|---|
| PatriciaTrie | O(k) | O(k) | Low | Prefix search, autocomplete |
| PatriciaSuffixTrie | O(k²) | O(k) | Medium | Substring search |
| SuffixTrie | O(k²) | O(k) | High | Suffix-based search |
| UkkonenTrie | O(k) | O(k) | Medium | Large text indexing |
| ConcurrentTrie | O(k) | O(k) | Medium | Multi-threaded scenarios |
where k is the length of the string
Choosing the Right Data Structure
Use PatriciaTrie when:
- You need prefix-based searching (autocomplete, type-ahead)
- Memory efficiency is important
- Your strings share common prefixes
- You only need to find strings that START with a query
Use PatriciaSuffixTrie when:
- You need substring searching (find strings CONTAINING a query)
- You want to find all occurrences of a pattern
- Memory usage is acceptable
- Query strings have a minimum length
Use UkkonenTrie when:
- You're indexing large amounts of text
- You need the most efficient suffix tree construction
- Substring search performance is critical
- You have complex pattern matching requirements
Use ConcurrentTrie when:
- Multiple threads need to access the trie simultaneously
- Thread safety is required
- You're building a shared index in a multi-threaded application
Important Notes
Case Sensitivity: Most examples use
.ToLower()for case-insensitive search. The trie itself is case-sensitive.Minimum Query Length: Suffix tries accept a minimum query/suffix length to reduce memory usage and improve performance.
Duplicate Values:
Retrieve()may return duplicate values if the same value was added with different keys. Use.Distinct()if needed.Remove Operations:
Remove()removes all occurrences of a value, regardless of which keys it was added with.Thread Safety: Only
ConcurrentTrieis thread-safe. Other implementations require external synchronization for concurrent access.
Target Frameworks
- .NET Standard 2.0
- .NET 6.0
- .NET 10.0
License
This code is distributed under MIT license. Copyright (c) 2013 George Mamaladze See license.txt or http://opensource.org/licenses/mit-license.php
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Ecng.Collections (>= 1.0.263)
-
net10.0
- Ecng.Collections (>= 1.0.263)
-
net6.0
- Ecng.Collections (>= 1.0.263)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Ecng.StringSearch:
| Package | Downloads |
|---|---|
|
StockSharp.Algo
Trading algorithms. More info on web site https://stocksharp.com/store/ |
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Ecng.StringSearch:
| Repository | Stars |
|---|---|
|
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
|
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.220 | 44 | 12/22/2025 |
| 1.0.219 | 49 | 12/21/2025 |
| 1.0.218 | 195 | 12/19/2025 |
| 1.0.217 | 188 | 12/19/2025 |
| 1.0.216 | 308 | 12/17/2025 |
| 1.0.215 | 309 | 12/15/2025 |
| 1.0.214 | 241 | 12/15/2025 |
| 1.0.213 | 218 | 12/14/2025 |
| 1.0.212 | 146 | 12/12/2025 |
| 1.0.211 | 107 | 12/12/2025 |
| 1.0.210 | 99 | 12/12/2025 |
| 1.0.209 | 105 | 12/12/2025 |
| 1.0.208 | 109 | 12/12/2025 |
| 1.0.207 | 765 | 12/2/2025 |
| 1.0.206 | 656 | 12/2/2025 |
| 1.0.205 | 657 | 12/2/2025 |
| 1.0.204 | 262 | 11/30/2025 |
| 1.0.203 | 117 | 11/29/2025 |
| 1.0.202 | 120 | 11/28/2025 |
| 1.0.201 | 118 | 11/28/2025 |
| 1.0.200 | 180 | 11/27/2025 |
| 1.0.199 | 279 | 11/24/2025 |
| 1.0.198 | 196 | 11/24/2025 |
| 1.0.197 | 206 | 11/23/2025 |
| 1.0.196 | 244 | 11/22/2025 |
| 1.0.195 | 471 | 11/20/2025 |
| 1.0.194 | 431 | 11/18/2025 |
| 1.0.193 | 389 | 11/18/2025 |
| 1.0.192 | 374 | 11/13/2025 |
| 1.0.191 | 275 | 11/10/2025 |
| 1.0.190 | 1,136 | 11/1/2025 |
| 1.0.189 | 234 | 10/28/2025 |
| 1.0.188 | 235 | 10/27/2025 |
| 1.0.187 | 185 | 10/27/2025 |
| 1.0.186 | 115 | 10/25/2025 |
| 1.0.185 | 1,189 | 10/3/2025 |
| 1.0.184 | 334 | 9/28/2025 |
| 1.0.183 | 258 | 9/25/2025 |
| 1.0.182 | 3,519 | 8/30/2025 |
| 1.0.181 | 2,707 | 7/13/2025 |
| 1.0.180 | 194 | 7/13/2025 |
| 1.0.179 | 168 | 7/12/2025 |
| 1.0.178 | 490 | 7/8/2025 |
| 1.0.177 | 465 | 7/4/2025 |
| 1.0.176 | 220 | 7/2/2025 |
| 1.0.175 | 1,477 | 6/16/2025 |
| 1.0.174 | 355 | 6/9/2025 |
| 1.0.173 | 258 | 6/8/2025 |
| 1.0.172 | 616 | 5/21/2025 |
| 1.0.171 | 186 | 5/17/2025 |
| 1.0.170 | 693 | 5/12/2025 |
| 1.0.169 | 266 | 5/12/2025 |
| 1.0.168 | 354 | 4/17/2025 |
| 1.0.167 | 1,405 | 3/22/2025 |
| 1.0.166 | 226 | 3/20/2025 |
| 1.0.165 | 210 | 3/20/2025 |
| 1.0.164 | 213 | 3/19/2025 |
| 1.0.163 | 1,103 | 2/26/2025 |
| 1.0.162 | 159 | 2/26/2025 |
| 1.0.161 | 1,325 | 2/5/2025 |
| 1.0.160 | 243 | 1/21/2025 |
| 1.0.159 | 178 | 1/14/2025 |
| 1.0.158 | 173 | 1/12/2025 |
| 1.0.157 | 181 | 1/10/2025 |
| 1.0.156 | 1,485 | 12/27/2024 |
| 1.0.155 | 360 | 11/20/2024 |
| 1.0.154 | 1,127 | 11/18/2024 |
| 1.0.153 | 503 | 11/7/2024 |
| 1.0.152 | 314 | 10/19/2024 |
| 1.0.151 | 889 | 10/12/2024 |
| 1.0.150 | 771 | 10/5/2024 |
| 1.0.149 | 1,165 | 9/18/2024 |
| 1.0.148 | 201 | 9/17/2024 |
| 1.0.147 | 888 | 9/3/2024 |
| 1.0.146 | 204 | 9/1/2024 |
| 1.0.145 | 3,638 | 6/12/2024 |
| 1.0.144 | 702 | 5/28/2024 |
| 1.0.143 | 1,319 | 5/4/2024 |
| 1.0.142 | 861 | 4/23/2024 |
| 1.0.141 | 211 | 4/21/2024 |
| 1.0.140 | 211 | 4/14/2024 |
| 1.0.139 | 1,097 | 3/28/2024 |
| 1.0.138 | 278 | 3/17/2024 |
| 1.0.137 | 1,360 | 2/23/2024 |
| 1.0.136 | 238 | 2/23/2024 |
| 1.0.135 | 1,002 | 2/18/2024 |
| 1.0.134 | 243 | 2/18/2024 |
| 1.0.133 | 259 | 2/16/2024 |
| 1.0.132 | 825 | 2/13/2024 |
| 1.0.131 | 715 | 2/8/2024 |
| 1.0.130 | 971 | 2/5/2024 |
| 1.0.129 | 273 | 2/4/2024 |
| 1.0.128 | 990 | 1/23/2024 |
| 1.0.127 | 267 | 1/23/2024 |
| 1.0.126 | 995 | 1/12/2024 |
| 1.0.125 | 1,093 | 1/2/2024 |
| 1.0.124 | 326 | 12/29/2023 |
| 1.0.123 | 3,248 | 11/12/2023 |
| 1.0.122 | 342 | 11/10/2023 |
| 1.0.121 | 306 | 11/10/2023 |
| 1.0.120 | 329 | 11/9/2023 |
| 1.0.119 | 361 | 11/3/2023 |
| 1.0.118 | 374 | 11/1/2023 |
| 1.0.117 | 325 | 11/1/2023 |
| 1.0.116 | 4,257 | 9/8/2023 |
| 1.0.115 | 423 | 9/8/2023 |
| 1.0.114 | 466 | 9/3/2023 |
| 1.0.113 | 557 | 8/21/2023 |
| 1.0.112 | 531 | 8/14/2023 |
| 1.0.111 | 563 | 8/10/2023 |
| 1.0.110 | 3,944 | 6/29/2023 |
| 1.0.109 | 2,163 | 5/27/2023 |
| 1.0.108 | 624 | 5/21/2023 |
| 1.0.107 | 608 | 5/19/2023 |
| 1.0.106 | 2,504 | 5/8/2023 |
| 1.0.105 | 684 | 4/21/2023 |
| 1.0.104 | 4,253 | 4/3/2023 |
| 1.0.103 | 827 | 3/13/2023 |
| 1.0.102 | 2,156 | 3/6/2023 |
| 1.0.101 | 708 | 2/26/2023 |
| 1.0.100 | 2,469 | 2/21/2023 |
| 1.0.99 | 663 | 2/20/2023 |
| 1.0.98 | 709 | 2/15/2023 |
| 1.0.97 | 687 | 2/14/2023 |
| 1.0.96 | 3,298 | 2/9/2023 |
| 1.0.95 | 2,349 | 2/7/2023 |
| 1.0.94 | 731 | 2/4/2023 |
| 1.0.93 | 2,469 | 2/2/2023 |
| 1.0.92 | 2,512 | 1/30/2023 |
| 1.0.91 | 819 | 1/18/2023 |
| 1.0.90 | 5,082 | 12/30/2022 |
| 1.0.89 | 748 | 12/23/2022 |
| 1.0.88 | 3,054 | 12/12/2022 |
| 1.0.87 | 2,791 | 12/4/2022 |
| 1.0.86 | 799 | 12/4/2022 |
| 1.0.85 | 770 | 11/30/2022 |
| 1.0.84 | 796 | 11/29/2022 |
| 1.0.83 | 787 | 11/28/2022 |
| 1.0.82 | 820 | 11/18/2022 |
| 1.0.81 | 3,387 | 11/11/2022 |
| 1.0.80 | 819 | 11/11/2022 |
| 1.0.79 | 834 | 11/10/2022 |
| 1.0.78 | 842 | 11/5/2022 |
| 1.0.77 | 822 | 11/4/2022 |
| 1.0.76 | 18,848 | 11/1/2022 |
| 1.0.75 | 21,105 | 10/16/2022 |
| 1.0.74 | 1,019 | 9/10/2022 |
| 1.0.73 | 42,623 | 9/8/2022 |
| 1.0.72 | 899 | 9/8/2022 |
| 1.0.71 | 938 | 9/8/2022 |
| 1.0.70 | 926 | 9/4/2022 |
| 1.0.69 | 83,765 | 8/24/2022 |
| 1.0.68 | 948 | 8/8/2022 |
| 1.0.67 | 962 | 7/26/2022 |
| 1.0.66 | 867 | 7/26/2022 |
| 1.0.65 | 43,442 | 7/19/2022 |
| 1.0.64 | 42,656 | 7/18/2022 |
| 1.0.63 | 948 | 7/8/2022 |
| 1.0.62 | 972 | 6/18/2022 |
| 1.0.61 | 959 | 6/6/2022 |
| 1.0.60 | 84,873 | 4/30/2022 |
| 1.0.59 | 948 | 4/20/2022 |
| 1.0.58 | 986 | 4/10/2022 |
| 1.0.57 | 981 | 4/7/2022 |
| 1.0.56 | 935 | 4/7/2022 |
| 1.0.55 | 1,001 | 4/2/2022 |
| 1.0.54 | 7,709 | 3/29/2022 |
| 1.0.53 | 934 | 3/27/2022 |
| 1.0.52 | 223,255 | 1/24/2022 |
| 1.0.51 | 144,854 | 12/29/2021 |
| 1.0.50 | 26,055 | 12/20/2021 |
| 1.0.49 | 848 | 12/13/2021 |
| 1.0.48 | 51,043 | 12/6/2021 |
| 1.0.47 | 826 | 12/2/2021 |
| 1.0.46 | 27,893 | 11/29/2021 |
| 1.0.45 | 26,014 | 11/22/2021 |
| 1.0.44 | 890 | 11/17/2021 |
| 1.0.43 | 26,912 | 11/13/2021 |
| 1.0.42 | 876 | 11/10/2021 |
| 1.0.41 | 837 | 11/9/2021 |
| 1.0.40 | 56,649 | 11/5/2021 |
| 1.0.39 | 847 | 11/4/2021 |
| 1.0.38 | 841 | 11/4/2021 |
| 1.0.37 | 882 | 11/3/2021 |
| 1.0.36 | 945 | 10/30/2021 |
| 1.0.35 | 29,712 | 10/21/2021 |
| 1.0.34 | 909 | 10/17/2021 |
| 1.0.33 | 55,808 | 10/14/2021 |
| 1.0.32 | 4,902 | 10/13/2021 |
| 1.0.31 | 868 | 10/12/2021 |
| 1.0.30 | 29,343 | 10/11/2021 |
| 1.0.29 | 882 | 10/9/2021 |
| 1.0.28 | 32,832 | 10/7/2021 |
| 1.0.27 | 31,402 | 10/7/2021 |
| 1.0.26 | 829 | 10/7/2021 |
| 1.0.25 | 860 | 10/6/2021 |
| 1.0.24 | 855 | 9/28/2021 |
| 1.0.23 | 30,463 | 9/23/2021 |
| 1.0.22 | 936 | 9/10/2021 |
| 1.0.21 | 890 | 9/9/2021 |
| 1.0.20 | 857 | 9/8/2021 |
| 1.0.19 | 834 | 9/8/2021 |
| 1.0.18 | 29,053 | 9/6/2021 |
| 1.0.17 | 901 | 8/31/2021 |
| 1.0.16 | 838 | 8/30/2021 |
| 1.0.15 | 30,026 | 7/31/2021 |
| 1.0.14 | 55,177 | 7/30/2021 |
| 1.0.13 | 953 | 7/26/2021 |
| 1.0.12 | 82,633 | 7/5/2021 |
| 1.0.11 | 817 | 7/1/2021 |
| 1.0.10 | 57,875 | 6/4/2021 |
| 1.0.9 | 83,470 | 4/26/2021 |
| 1.0.8 | 29,092 | 4/19/2021 |
| 1.0.7 | 136,305 | 4/7/2021 |
| 1.0.6 | 28,324 | 4/3/2021 |
| 1.0.5 | 163,814 | 3/22/2021 |
| 1.0.4 | 102,415 | 3/4/2021 |
| 1.0.3 | 28,189 | 2/26/2021 |
| 1.0.2 | 152,063 | 2/2/2021 |
| 1.0.1 | 101,901 | 1/24/2021 |
| 1.0.0 | 963 | 1/24/2021 |