В этом конкретном примере я бы предложил использовать распаковку, чтобы сделать понимание списка более ясным:
output = [p for p in people for name,_,_,pet in [p.split()] if name in names and pet == "cat" ]
Вы также можете использовать map, чтобы разбить строки в сингле для l oop:
output = [" ".join(p) for p in map(str.split,people) if p[0] in names and p[3] == "cat" ]
или почтовый индекс и карта, чтобы избежать восстановления строк:
output = [p for p,(name,_,_,pet) in zip(people,map(str.split,people)) if name in names and pet == "cat"]