Как отсортировать список питонов, проверяя, соответствует ли он заданному шаблону? - PullRequest
0 голосов
/ 06 февраля 2019

Извините за мой английский.

Я делаю программу tkinter на python, но я застрял на пути сортировки списка.Позвольте мне объяснить вам.

Я хочу создать функцию, которая принимает список строк (пользовательский ввод) в качестве аргумента и возвращает тот же список в другом порядке в зависимости от того, соответствуют ли их элементы определенным словарным ключам.

Я поставил в диктанте порядок, связанный с каждой клавишей.

dic=dict(organiza=1,autor=1,direct=1,docen=1,exp=1,dirig=1,ponen=1,fecha=2,día=2,dia=2,cuándo=2,cuando=2,lugar=3,sitio=3,locali=3,situa=3,direcci=3,ubica=3,web=4,link=4,enlace=4,página=4,pagina=4)

Я хочу этого, если я возьму список вроде:

    lis=['TITLE:BLAH,BLAH..', 'web: www.something.es', 'situación: UCM University', 'Director: Someone', 'Fecha: some date']

выходные данные должны быть:

    ['TITLE:BLAH,BLAH..','Director: Someone', 'Fecha: some date', 'situación: UCM University' 'web: www.something.es']

то есть, порядок, который я хочу, будет следующим: «НАЗВАНИЕ (это первое изменение, а не изменение), Директор, Fecha, Ситуация, Сеть» или варианты их значений.

Поскольку программа должна проверить список и сравнить его с ключами dict, сортируя его по значениям dict.Как видите, нет необходимости сопоставлять каждую строку слова в целом, если какая-то часть слова соответствует некоторой клавише ДО ":", это необходимо учитывать для сортировки.

    texto=self.master.clipboard_get() #obtenemos un string del clipboard
    texto=texto.split('\n') #separamos cada parrafo en una entrada de una lista
    texto=list(map(str.strip,texto)) #eliminamos posibles espacios iniciales y finales en cada entrada
    N=len(texto) #medimos su longitud
    x=[] #inicializamos la lista de items no deseados
    for i in range(N): #recorremos cada elemento de la lista
        n=len(texto[i]) #longitud del elemento en cuestion
        check=texto[i]==' '*n #si el elemento es solo espacio en blanco
        if check==True:
            x.append(texto[i]) #añadimos el item no deseado
    texto = [e for e in texto if e not in x] #con esto ya tenemos la lista con las entradas a poner en los campos
    N=len(texto) #volvemos a medir su longitud
    if N>5:
        return messagebox.showerror("Atención", "El texto que desea pegar tiene más de 5 líneas. El número de campos debe ser compatible con las celdas que se desea rellenar.")
    elif N<5: #si es menor que 5 completamos campos con entradas vacias
        while len(texto)<5:
            texto.append('')
    dic=dict(organiza=1,autor=1,direct=1,docen=1,exp=1,dirig=1,ponen=1,fecha=2,día=2,dia=2,cuándo=2,cuando=2,lugar=3,sitio=3,locali=3,situa=3,direcci=3,ubica=3,web=4,link=4,enlace=4,página=4,pagina=4)#diccionario con el orden de las claves
    new_order=[i for i in range(5)] #lista que llevara los nuevos ordenes de texto
    iteracion=itertools.product(range(1,N), dic.keys())
    for i, j in iteracion: #un loop es sobre el vector texto y otro sobre las claves del diccionario
        if texto[i].lower().find(j,0,texto[i].find(':'))!=-1: #si en alguna entrada del vector texto encuentra alguna clave j antes de los :
            new_order[i]=dic[j] #en el vector de nuevas posiciones asignamos la que nos dice el diccionario
    texto=[x for _,x in sorted(zip(new_order,texto))]
    self.var_entry_titulo.set(texto[0])
    self.var_entry_director.set(texto[1][texto[1].find(':')+1:].strip())
    self.var_entry_fecha.set(texto[2][texto[2].find(':')+1:].strip())
    self.var_entry_lugar.set(texto[3][texto[3].find(':')+1:].strip())
    self.var_entry_web.set(texto[4][texto[4].find(':')+1:].strip())
    print(texto,new_order)

Код выше не работает вообще.Я много пробовал, но не получается.

Спасибо всем, надеюсь, вы понимаете, что я пытаюсь объяснить, но я знаю, что это очень плохая аргументация

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019
dic = {'title':0,'organiza':1,'autor':1,'direct':1,'docen':1,'exp':1,'dirig':1,'ponen':1,'fecha':2,'día':2,'dia':2,'cuándo':2,'cuando':2,'lugar':3,'sitio':3,'locali':3,'situa':3,'direcci':3,'ubica':3,'web':4,'link':4,'enlace':4,'página':4,'pagina':4}

lis = ['TITLE:BLAH,BLAH..', 'web: www.something.es', 'situación: UCM University', 'Director: Someone', 'Fecha: some date']

def get_ordered_add(value):
    keys = dic.keys()
    title = value.split(":")[0].lower()
    return  [dic[kys]
                 for kys in keys 
                 if title.startswith(kys)][0]

sorted(lis, key=get_ordered_add)
>>>['TITLE:BLAH,BLAH..',
    'Director: Someone',
    'Fecha: some date',
    'situaci\xc3\xb3n: UCM University',
    'web: www.something.es']
0 голосов
/ 06 февраля 2019

Вам необходимо создать ключ сортировки, чтобы отсортировать по значению после ":".Функция «sort_key» возвращает строку после «:», которая будет параметром сортировки.

lis=['TITLE: BLAH,BLAH..', 'web: www.something.es', 'situación: UCM University', 'Director: Someone', 'Fecha: some date']
def sort_key(elem):
    return elem.split(': ')[1]
print(sorted(lis,key=sort_key))
0 голосов
/ 06 февраля 2019

Здесь вы можете попробовать:

dic=dict(organiza=1,autor=1,direct=1,docen=1,exp=1,dirig=1,ponen=1,fecha=2,día=2,dia=2,cuándo=2,cuando=2,lugar=3,sitio=3,locali=3,situa=3,direcci=3,ubica=3,web=4,link=4,enlace=4,página=4,pagina=4)
lis = ['TITLE:BLAH,BLAH..', 'web: www.something.es', 'situación: UCM University', 'Director: Someone',
   'Fecha: some date']
li = [[] for i in range(len(lis))]
li[0].append(lis[0])
for x in lis:
    for j in dic.keys():
        if j in x.split(':')[0].lower():
            li[dic[j]].append(x)

print(sum(li,[]))
# ['TITLE:BLAH,BLAH..', 'Director: Someone', 'Fecha: some date', 'situación: UCM University', 'web: www.something.es']
0 голосов
/ 06 февраля 2019

В словаре в вопросе отсутствует ключ для «заголовка», который должен иметь значение ноль, потому что он идет первым.Кроме того, вы должны использовать параметр key при вызове процедуры sorted, это значительно упрощает проблему.Вот мое предложение:

import re

# this is the preferred syntax for creating a dictionary
dic = {'title':0,'organiza':1,'autor':1,'direct':1,'docen':1,'exp':1,'dirig':1,'ponen':1,'fecha':2,'día':2,'dia':2,'cuándo':2,'cuando':2,'lugar':3,'sitio':3,'locali':3,'situa':3,'direcci':3,'ubica':3,'web':4,'link':4,'enlace':4,'página':4,'pagina':4}

def rank(ele):
    # split each element in words
    ele = ele.lower()
    words = re.split(r'[: ]+', ele)
    # check each word to see if it's a
    # substring of one of the dictionary keys
    for w in words:
        for word, value in dic.items():
            if word in w:
                # return first match
                return value
    # if no match is found, send word to the end
    return float('+inf')

Работает как положено:

lis = ['TITLE:BLAH,BLAH..', 'web: www.something.es', 'situación: UCM University', 'Director: Someone', 'Fecha: some date']
sorted(lis, key=rank)
=> ['TITLE:BLAH,BLAH..', 'Director: Someone', 'Fecha: some date', 'situación: UCM University', 'web: www.something.es']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...