анализ данных с использованием регулярных выражений и преобразование их в кортеж

#python #regex

#python #регулярное выражение

Вопрос:

Мне нужно найти город с наибольшим населением, используя регулярные выражения, данные представлены таким образом:

 data = ["id,name,poppulation,is_capital",
"3024,eu_kyiv,24834,y",
"3025,eu_volynia,20231,n",
"3026,eu_galych,23745,n",
"4892,me_medina,18038,n",
"4401,af_cairo,18946,y",
"4700,me_tabriz,13421,n",
"4899,me_bagdad,22723,y",
"6600,af_zulu,09720,n"]
 

Я делал это до сих пор:

 def max_population(data):
    lst = []
    for items in data:
        a = re.findall(r',S _S ,[0-9] ', items)
        lst  = [[b for b in i.split(',') if b] for i in a]
    return max(lst, key=lambda x:int(x[1]))
 

Но функция должна возвращать (str, int) кортеж, возможно ли изменить мой код таким образом, чтобы он возвращал кортеж без повторения списка еще раз?

Ответ №1:

Все ваши строки разделяются запятой. Вы можете получить максимальное значение с помощью split и проверить, является ли третье значение цифрой и больше первого значения кортежа.

Если это так, установите его как новое наибольшее значение.

 def max_population(data):
    result = None
    for s in data:
        parts = s.split(",")
        if not parts[2].isdigit():
            continue
        tup = (parts[1], int(parts[2]))
        if result is None or tup[1] > result[1]:
            result = tup

    return result


print(max_population(items))
 

Вывод

 ('eu_kyiv', 24834)
 

Демонстрация Python

Ответ №2:

Следующая длинная строка дает желаемый результат (str, int) tuple :

 def max_population(data):
    p=max([(re.findall(r"(w*),d*,w$",i)[0],int(re.findall(r"(d*),w$",i)[0])) for n,i in enumerate(data) if n>0],key=lambda x:int(x[1]) )
    return p
 

в этой строке enumerate(data) и n>0 использовались для пропуска заголовка "id,name,poppulation,is_capital" . Но если data нет заголовка, строка будет:

 def max_population(data):
    p=max([(re.findall(r"(w*),d*,w$",i)[0],int(re.findall(r"(d*),w$",i)[0])) for i in data],key=lambda x:int(x[1]) )
    return p
 

Результат для обоих ('eu_kyiv', 24834)

Ответ №3:

Создайте список кортежей вместо списка списков.

 import re

data = ["id,name,poppulation,is_capital",
"3024,eu_kyiv,24834,y",
"3025,eu_volynia,20231,n",
"3026,eu_galych,23745,n",
"4892,me_medina,18038,n",
"4401,af_cairo,18946,y",
"4700,me_tabriz,13421,n",
"4899,me_bagdad,22723,y",
"6600,af_zulu,09720,n"]

def max_population(data):
    lst = []
    for items in data:
        a = re.findall(r',S _S ,[0-9] ', items)
        lst  = [tuple(b for b in i.split(',') if b) for i in a]
    return max(lst, key=lambda x:int(x[1]))

print(max_population(data))
 

Ответ №4:

Вы могли бы создать функцию сопоставления для сопоставления типов с данными и использовать эту operator.itemgetter функцию в качестве ключа в max :

 from operator import itemgetter

def f(row):
   # Use a tuple of types to cast str to the desired type
   types = (str, int)
   # slice here to get the city and population values
   return tuple(t(val) for t, val in zip(types, row.split(',')[1:3]))


# Have max consume a map on the data excluding the
# header row (hence the slice)
max(map(f, data[1:]), key=itemgetter(1))
('eu_kyiv', 24834)