Skip to content

Instantly share code, notes, and snippets.

@skritch
Created November 18, 2016 01:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skritch/f19c1b1e52e02289d3ffb45d62ae201d to your computer and use it in GitHub Desktop.
Save skritch/f19c1b1e52e02289d3ffb45d62ae201d to your computer and use it in GitHub Desktop.
from itertools import imap
import json
class Map(object):
def __init__(self, iterable, steps=[]):
"""
Construct an iterator that looks up items in the given iterable by index, key, field name, or calls
a function on them.
:param iterable: An iterable of "objects"
"""
self.iterable = iterable
self.steps = steps
def from_existing(self, new_step):
steps = list(self.steps) + [new_step]
return Map(self.iterable, steps)
def __getattr__(self, name):
return self.from_existing(lambda i: getattr(i, name))
def __getitem__(self, key):
return self.from_existing(lambda i: i[key])
def get(self, key, default=None):
return self.from_existing(lambda i: self._get_even_from_list(i, key, default))
def __or__(self, func):
return self.from_existing(func)
def __call__(self):
return list(self.__iter__())
@staticmethod
def _get_even_from_list(obj, key, default=None):
if isinstance(obj, dict):
return obj.get(key, default)
try:
return obj[key]
except IndexError:
return default
def __repr__(self):
return "<MapGet({}) steps={}>".format(self.iterable, self.steps)
def __iter__(self):
return imap(
reduce(
lambda f, g: lambda x: g(f(x)), # function composition
self.steps,
lambda x: x # initializer
),
self.iterable
)
if __name__ == '__main__':
obj = [{"x":[{"y":{"z":5}}]}, {"x":[{"y":{"z":6}}]}]
m1 = Map(obj)["x"][0]["y"]
m2 = Map(m1)
print((m1 | json.dumps)())
print((m2['z'] | (lambda x: x**2))())
# ['{"z": 5}', '{"z": 6}']
# [25, 36]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment