fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace TransitiveGroupBy
  8. {
  9. static class EnumerableExtensions
  10. {
  11. class TransitiveGrouping<K, T> : List<T>, IGrouping<K, T>
  12. {
  13. public TransitiveGrouping(K key) { Key = key; }
  14. public K Key { get; private set; }
  15. internal List<K> EqualKeys = new List<K>();
  16. }
  17.  
  18. public static IEnumerable<IGrouping<K, T>> TransitiveGroupBy<T, K>(
  19. this IEnumerable<T> sequence,
  20. Func<T, K> keySelector,
  21. Func<K, K, bool> keyComparer)
  22. {
  23. var result = new List<TransitiveGrouping<K, T>>();
  24. foreach (T curr in sequence)
  25. {
  26. K currKey = keySelector(curr);
  27. var containingGroups = result
  28. .Where(tg => tg.EqualKeys.Any(kk => keyComparer(kk, currKey)))
  29. .ToList();
  30. if (containingGroups.Count == 0)
  31. {
  32. // add a new group
  33. var newGroup = new TransitiveGrouping<K, T>(currKey);
  34. newGroup.Add(curr);
  35. newGroup.EqualKeys.Add(currKey);
  36. result.Add(newGroup);
  37. }
  38. else
  39. {
  40. var targetGroup = containingGroups.First();
  41. targetGroup.Add(curr);
  42. // merge the groups (transitive closure)
  43. foreach (var group in containingGroups.Skip(1))
  44. {
  45. targetGroup.AddRange(group);
  46. targetGroup.EqualKeys.AddRange(group.EqualKeys);
  47. result.Remove(group);
  48. }
  49. }
  50. }
  51. return result;
  52. }
  53. }
  54.  
  55. internal static class StringIncludeComparer
  56. {
  57. public static bool Equals(string x, string y)
  58. {
  59. if (x.ToUpper().Contains(y.ToUpper())) { return true; }
  60. if (y.ToUpper().Contains(x.ToUpper())) { return true; }
  61. return false;
  62. }
  63. }
  64.  
  65. class Program
  66. {
  67. static void Main(string[] args)
  68. {
  69. var values = new List<string>
  70. {
  71. "поставить печать",
  72. "не ставить печать",
  73. "Поставить печать!!!",
  74. "Поставить печать??"
  75. };
  76.  
  77.  
  78. var values2 = new List<string>
  79. {
  80. "Поставить печать!!!",
  81. "не ставить печать",
  82. "Поставить печать??",
  83. "поставить печать"
  84. };
  85.  
  86. foreach (var s in values2.TransitiveGroupBy(s => s, StringIncludeComparer.Equals)
  87. .Select(g => g.OrderByDescending(s => s.Length).First()))
  88. Console.WriteLine(s);
  89.  
  90. foreach (var s in values2.TransitiveGroupBy(s => s, StringIncludeComparer.Equals)
  91. .Select(g => g.OrderByDescending(s => s.Length).First()))
  92. Console.WriteLine(s);
  93. }
  94. }
  95. }
  96.  
Success #stdin #stdout 0.06s 24632KB
stdin
Standard input is empty
stdout
Поставить печать!!!
не ставить печать
Поставить печать!!!
не ставить печать