code: def join(keys, tables):
      
  
      # Make new (merged) Table fields
      fields = OrderedDict()
      for table in tables:
          fields.update(table.fields)
      # TODO: may raise an error if a same field is different in some tables
  
      # Check if all keys are inside merged Table's fields
      fields_keys = set(fields.keys())
      for key in keys:
          if key not in fields_keys:
              raise ValueError('Invalid key: "{}"'.format(key))
  
      # Group rows by key, without missing ordering
      none_fields = lambda: OrderedDict({field: None for field in fields.keys()})
      data = OrderedDict()
      for table in tables:
          for row in table:
              row_key = tuple([getattr(row, key) for key in keys])
              if row_key not in data:
                  data[row_key] = none_fields()
              data[row_key].update(row._asdict())
  
      merged = Table(fields=fields)
      merged.extend(data.values())
      return merged
docs: Merge a list of `Table` objects using `keys` to group rows