Advertisement
Unchpokable

Ulearn "PocketGoogle" task

Dec 19th, 2020
662
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.58 KB | None | 0 0
  1. namespace PocketGoogle
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Linq;
  6.  
  7.     public class Indexer : IIndexer
  8.     {
  9.         protected Registry<string, int, List<int>> registry;
  10.         private readonly HashSet<char> stdSeparators = new HashSet<char>() { ' ', '.', ',', '!', '?', ':', '-', '\r', '\n' };
  11.  
  12.         public Indexer()
  13.         {
  14.             registry = new Registry<string, int, List<int>>();
  15.         }
  16.  
  17.         public void Add(int id, string documentText)
  18.         {
  19.             int pointer = 0;
  20.             while (pointer < documentText.Length)
  21.             {
  22.                 pointer = SkipSeparators(pointer, documentText);
  23.                 var length = GetPartLength(documentText, pointer);
  24.                 var word = documentText.Substring(pointer, length);
  25.                 AddToRegistry(id, pointer, word);
  26.                 pointer += length;
  27.             }
  28.         }
  29.  
  30.         public List<int> GetIds(string word)
  31.         {
  32.             return registry.GetNestedKeys(word).ToList();
  33.         }
  34.  
  35.         public List<int> GetPositions(int id, string word)
  36.         {
  37.             if (registry.ContainsKey(word))
  38.             {
  39.                 if (registry[word].ContainsKey(id))
  40.                     return registry[word][id];
  41.             }
  42.             return new List<int>();
  43.         }
  44.  
  45.         public void Remove(int id)
  46.         {
  47.             registry.Cleanup(id);
  48.         }
  49.  
  50.         private int GetPartLength(string src, int startFrom)
  51.         {
  52.             var end = startFrom;
  53.             while (end < src.Length && !stdSeparators.Contains(src[end]))
  54.                 end++;
  55.             return end - startFrom;
  56.         }
  57.  
  58.         private int SkipSeparators(int pointer, string documentText)
  59.         {
  60.             var temp = pointer;
  61.             while (temp < documentText.Length && stdSeparators.Contains(documentText[temp]))
  62.                 temp++;
  63.             return temp;
  64.         }
  65.  
  66.         private void AddToRegistry(int docID, int pos, string word)
  67.         {
  68.             if (registry.ContainsKey(word))
  69.             {
  70.                 if (registry[word].ContainsKey(docID))
  71.                     registry[word][docID].Add(pos);
  72.                 else
  73.                     registry[word].Add(docID, new List<int>() { pos });
  74.                 return;
  75.             }
  76.  
  77.             registry.AddBranch(word, new Dictionary<int, List<int>>() { { docID, new List<int>() { pos } } });
  78.         }
  79.     }
  80.  
  81.     public sealed class Registry<TRoot, TKey, TValue> : Dictionary<TRoot, Dictionary<TKey, TValue>>
  82.     {
  83.         //Класс унаследован от стандартного типа, по этому добавлены все конструкторы, объявленные в Dictionary<>
  84.         //За исключением конструктора с параметрами для сериализации, ибо Registry<> сериализацию не поддерживает. Хотя, в идеале, надо бы.
  85.         public Registry() : base() { }
  86.         public Registry(int depth) : base(depth) { }
  87.         public Registry(IEqualityComparer<TRoot> comparer) : base(comparer) { }
  88.         public Registry(IDictionary<TRoot, Dictionary<TKey, TValue>> initiator) : base(initiator) { }
  89.         public Registry(int depth, IEqualityComparer<TRoot> comparer) : base(depth, comparer) { }
  90.         public Registry(IDictionary<TRoot, Dictionary<TKey, TValue>> initiator, IEqualityComparer<TRoot> comparer) : base(initiator, comparer) { }
  91.  
  92.         public void AddBranch(TRoot branchID, Dictionary<TKey, TValue> branch)
  93.         {
  94.             if (ContainsKey(branchID))
  95.                 throw new RegistryBranchCreationException($"Can not create new branch with ID {branchID}, cause branch with such ID already exists");
  96.             Add(branchID, branch);
  97.         }
  98.  
  99.         public void BranchExtend(TRoot branchID, Dictionary<TKey, TValue> branch)
  100.         {
  101.             if (ContainsKey(branchID))
  102.             {
  103.                 foreach (var pair in branch)
  104.                     this[branchID].Add(pair.Key, pair.Value);
  105.                 return;
  106.             }
  107.             AddBranch(branchID, branch);
  108.         }
  109.  
  110.         /// <summary>
  111.         /// Возвращает все ключи, находящиеся в разделе указанного корневого ключа
  112.         /// </summary>
  113.         /// <param name="rootKey">Корневой ключ</param>
  114.         public IList<TKey> GetNestedKeys(TRoot rootKey)
  115.         {
  116.             if (!ContainsKey(rootKey))
  117.                 return new List<TKey>();
  118.             return this[rootKey].Keys.ToList();
  119.         }
  120.  
  121.         /// <summary>
  122.         /// Перебирает все корневые ключи реестра, определяя наличие в соответсвующем разлделе указанного вложенного ключа,
  123.         /// и удаляет его в случае обнаружения
  124.         /// </summary>
  125.         /// <param name="value">Искомое значение вложенного ключа</param>
  126.         public void Cleanup(TKey key)
  127.         {
  128.             foreach (var branch in Keys)
  129.             {
  130.                 this[branch].Remove(key);
  131.             }
  132.         }
  133.     }
  134.  
  135.     internal sealed class RegistryBranchCreationException : Exception
  136.     {
  137.         public RegistryBranchCreationException() : base() { }
  138.  
  139.         public RegistryBranchCreationException(string error) : base(error) { }
  140.        
  141.         public RegistryBranchCreationException(string error, Exception innerExc) : base(error, innerExc) { }
  142.     }
  143. }
  144.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement