# -*- coding: utf-8 -*- #!/usr/bin/env python # Francisco Mota, 2011-11-09 # http://fmota.eu/blog/monoids-in-python.html # see also: http://arxiv.org/abs/1304.7544 import math class Monoid(object): def __init__(self, null, lift, op): self.null = null self.lift = lift self.op = op def fold(self, xs): if hasattr(xs, "__fold__"): return xs.__fold__(self) else: return reduce(self.op, (self.lift(x) for x in xs), self.null) def __call__(self, *args): return self.fold(args) def star(self): return Monoid(self.null, self.fold, self.op) summ = Monoid(0, lambda x: x, lambda a, b: a + b) joinm = Monoid('', lambda x: str(x), lambda a, b: a + b) listm = Monoid([], lambda x: [x], lambda a, b: a + b) tuplem = Monoid((), lambda x: (x,), lambda a, b: a + b) lenm = Monoid(0, lambda x: 1, lambda a, b: a + b) prodm = Monoid(1, lambda x: x, lambda a, b: a * b) ## extended to define a monoid for folding Python `dict` def dict_op(a, b): for key, val in b.items(): if not key in a: a[key] = val else: if isinstance(val, dict): a[key] = dict_op(a[key], val) else: a[key] += val return a dictm = Monoid({}, lambda x: x, lambda a, b: dict_op(a, b)) class Haversine(object): """ half of the versed sine use the haversine class to calculate the distance between two lon/lat coordinate pairs. output distance available in kilometers, meters, miles, and feet. example usage: Haversine([lon1,lat1],[lon2,lat2]).feet """ def __init__(self, coord1, coord2): lon1, lat1 = coord1 lon2, lat2 = coord2 R = 6371000 # radius of Earth in meters phi_1 = math.radians(lat1) phi_2 = math.radians(lat2) delta_phi = math.radians(lat2 - lat1) delta_lambda = math.radians(lon2 - lon1) a = math.sin(delta_phi / 2.0) ** 2 + \ math.cos(phi_1) * math.cos(phi_2) * \ math.sin(delta_lambda / 2.0) ** 2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) self.meters = R * c # output distance in meters self.km = self.meters / 1000.0 # output distance in kilometers self.miles = self.meters * 0.000621371 # output distance in miles self.feet = self.miles * 5280 # output distance in feet def get_haversine_by_km(point1, point2): """ :param point1: :param point2: :return: """ return Haversine(point1, point2).km if __name__=='__main__': xs = [{ "a": i, "b": i + 1 } for i in range(0, 1000)] ys = [{ "a": i, "b": i } for i in range(0, 1000)] x1 = { "a": 2, "b": 3 } x2 = { "b": 2, "c": 7 } print x1, x2 print dictm.fold(xs + ys)