Из вашего вопроса не совсем понятно, в чем именно заключается проблема. Поскольку данные, которые вы привели в качестве примера, согласованы и хорошо упорядочены, эту проблему можно легко решить, просто разделив элементы в списке и распределив их по категориям.
loc_list = ["LONDON-UK-L16-N1", "LONDON-UK-L17-N1", "LONDON-UK-L16-N2",
"LONDON-UK-L16-N2", "PARIS-France-L16-N2"]
split_loc_list = [location.split("-") for location in loc_list]
locs = {}
for loc in split_loc_list:
locs.setdefault("-".join(loc[0:2]), {}).\
setdefault("L", set()).add(loc[2].strip("L"))
locs.setdefault("-".join(loc[0:2]), {}).\
setdefault("N", set()).add(loc[3].strip("N"))
for loc, vals in locs.items():
L_vals_sorted = sorted(list(map(int,vals["L"])))
L_vals_joined = "|".join(map(str,L_vals_sorted))
N_vals_sorted = sorted(list(map(int,vals["N"])))
N_vals_joined = "|".join(map(str,N_vals_sorted))
print(f"{loc}-L({L_vals_joined})-N({N_vals_joined})")
выведет:
LONDON-UK-L(16|17)-N(1|2)
PARIS-France-L(16)-N(2)
Поскольку здесь было только два тега ("L" и "N"), я просто записал их в код. Если существует много возможных тегов, то вы можете вырезать любую букву, используя:
import re
split = re.findall('\d+|\D+', loc[2])
key, val = split[0], split[1]
locs.setdefault("-".join(loc[0:2]), {}).\
setdefault(key, set()).add(val)
Затем выполните итерацию по всем тегам вместо простого извлечения «L» и «N» во втором l oop.