Guest User

Untitled

a guest
May 23rd, 2018
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.58 KB | None | 0 0
  1. import itertools
  2. import typing
  3. from pprint import pprint
  4.  
  5.  
  6. def full_join(d1: typing.Optional[dict], d2: typing.Optional[dict]) -> typing.Optional[dict]:
  7. if d1 is None or d2 is None:
  8. return None
  9. return {k: d1.get(k, d2.get(k)) for k in itertools.chain(d1, d2)}
  10.  
  11.  
  12. def left_join(d1: typing.Optional[dict], d2: typing.Optional[dict]) -> typing.Optional[dict]:
  13. if d1 is None:
  14. return None
  15. if d2 is None:
  16. return d1
  17. return full_join(d1, d2)
  18.  
  19.  
  20. def aggregate(
  21. g: typing.Iterator[dict],
  22. extract_key: typing.Callable[[typing.Dict], str]) -> typing.Iterator[typing.List[dict]]:
  23. last_values = last_key = []
  24. for e in g:
  25. if not last_values:
  26. last_values, last_key = [e], extract_key(e)
  27. elif last_key == extract_key(e):
  28. last_values.append(e)
  29. else:
  30. yield last_values
  31. last_values, last_key = [e], extract_key(e)
  32. if last_values:
  33. yield last_values
  34.  
  35.  
  36. def join(
  37. g1: typing.Iterator[dict],
  38. g2: typing.Iterator[dict],
  39. join_elements: typing.Callable[[typing.Optional[dict], typing.Optional[dict]], typing.Optional[dict]],
  40. extract_key: typing.Callable[[typing.Dict], str]) -> typing.Iterator[dict]:
  41. def yield_if_not_none(d1: typing.Optional[dict], d2: typing.Optional[dict]):
  42. result = join_elements(d1, d2)
  43. if result:
  44. yield result
  45.  
  46. i1, i2 = iter(g1), iter(g2)
  47. o1 = o2 = None
  48. while True:
  49. if not o1:
  50. try:
  51. o1 = next(i1)
  52. except StopIteration:
  53. return
  54. if not o2:
  55. try:
  56. o2 = next(i2)
  57. except StopIteration:
  58. o2 = None
  59.  
  60. if o2 is None:
  61. yield from yield_if_not_none(o1, None)
  62. else:
  63. k1, k2 = extract_key(o1), extract_key(o2)
  64. if k1 < k2:
  65. yield from yield_if_not_none(o1, None)
  66. o1 = None
  67. elif k1 > k2:
  68. yield from yield_if_not_none(None, o2)
  69. o2 = None
  70. else:
  71. yield from yield_if_not_none(o1, o2)
  72. o1 = o2 = None
  73.  
  74.  
  75. if __name__ == '__main__':
  76. u1 = ({'user_id': 'user_{:02}'.format(i), 'field1': i} for i in range(10))
  77. u2 = ({'user_id': 'user_{:02}'.format(i), 'field2': i} for i in range(1, 13, 2))
  78. u3 = ({'user_id': 'user_{:02}'.format(i), 'field1': i, 'fieldX': i // 3} for i in range(10))
  79. print('Join')
  80. pprint(list(join(u1, u2, left_join, lambda d: d['user_id'])))
  81. print('Aggregate')
  82. pprint(list(aggregate(u3, lambda d: d['fieldX'])))
Add Comment
Please, Sign In to add comment