Joins¶
Warning
Please, make sure you've covered Reference / Basics first.
c.join(left_conversion, right_conversion, condition, how="inner")
defines
join conversion, which returns an iterator of (left_element, right_element)
tuples.
left_conversion
defines the left part of a joinright_conversion
defines the right part of a joincondition
any condition defined as a conversion, wherec.LEFT
andc.RIGHT
reference elements of the left and right sequences.how
is any of"inner" | "left" | "right" | "outer"
from convtools import conversion as c
collection_1 = [
{"id": 1, "name": "Nick"},
{"id": 2, "name": "Joash"},
{"id": 3, "name": "Bob"},
]
collection_2 = [
{"ID": "3", "age": 17, "country": "GB"},
{"ID": "2", "age": 21, "country": "US"},
{"ID": "1", "age": 18, "country": "CA"},
]
input_data = (collection_1, collection_2)
conv = (
c.join(
c.item(0),
c.item(1),
c.and_(
c.LEFT.item("id") == c.RIGHT.item("ID").as_type(int),
c.RIGHT.item("age") >= 18,
),
how="left",
)
.pipe(
c.list_comp(
{
"id": c.item(0, "id"),
"name": c.item(0, "name"),
"age": c.item(1, "age", default=None),
"country": c.item(1, "country", default=None),
}
)
)
.gen_converter(debug=True)
)
assert conv(input_data) == [
{"id": 1, "name": "Nick", "age": 18, "country": "CA"},
{"id": 2, "name": "Joash", "age": 21, "country": "US"},
{"id": 3, "name": "Bob", "age": None, "country": None},
]
def aggregate_i(_none, data_, *, __v=__naive_values__["__v"]):
agg_data_i_v0 = _none
checksum_ = 0
it_ = iter(data_)
for row_i in it_:
if row_i["age"] >= 18:
if agg_data_i_v0 is _none:
checksum_ += 1
agg_data_i_v0 = defaultdict(list)
agg_data_i_v0[int(row_i["ID"])].append(row_i)
else:
agg_data_i_v0[int(row_i["ID"])].append(row_i)
if checksum_ == 1:
globals()["__BROKEN_EARLY__"] = True # DEBUG ONLY
break
for row_i in it_:
if row_i["age"] >= 18:
agg_data_i_v0[int(row_i["ID"])].append(row_i)
return __v if (agg_data_i_v0 is _none) else (setattr(agg_data_i_v0, "default_factory", None) or agg_data_i_v0)
def join_(left_, right_, _none):
hash_to_right_items = aggregate_i(_none, right_)
del right_
for left_item in left_:
left_key = left_item["id"]
right_items = iter(((hash_to_right_items[left_key] if (left_key in hash_to_right_items) else ())))
right_item = next(right_items, _none)
if right_item is _none:
yield left_item, None
else:
yield left_item, right_item
for right_item in right_items:
yield left_item, right_item
def converter(data_, *, __get_2_or_default=__naive_values__["__get_2_or_default"]):
global __none__
_none = __none__
try:
return [
{"id": i[0]["id"], "name": i[0]["name"], "age": __get_2_or_default(i, 1, "age", None), "country": __get_2_or_default(i, 1, "country", None)}
for i in join_(data_[0], data_[1], _none)
]
except __exceptions_to_dump_sources:
__convtools__code_storage.dump_sources()
raise