Obtenha a maior duração de uma lista de strings

8

Eu tenho uma lista de durações como abaixo

['5d', '20h', '1h', '7m', '14d', '1m']

onde dfica por dias, hfica por horas e mfica por minutos.

Eu quero obter a maior duração desta lista ( 14dneste caso). Como posso obter isso dessa lista de strings?

Rafiul Sabbir
fonte
1
stackoverflow.com/a/4628148/1224467 Esta resposta tem uma solução para transformar suas seqüências de caracteres em timedeltas. Estes podem ser classificados.
H4kor 17/01

Respostas:

12

Solução python pura. Poderíamos armazenar mapeamento entre nossas extensões de tempo ( m, h, d) e minutos (aqui time_map), para encontrar maior duração. Aqui estamos usando max()com keyargumento para aplicar o nosso mapeamento.

inp = ['5d', '20h', '1h', '7m', '14d', '1m']
time_map = {'m': 1, 'h': 60, 'd': 24*60}

print(max(inp, key=lambda x:int(x[:-1])*time_map[x[-1]]))  # -> 14d
Filip Młynarski
fonte
14

np.argmaxem pd.to_timedelta:

import numpy as np
import pandas as pd

durations = ['5d', '20h', '1h', '7m', '14d', '1m']

durations[np.argmax(pd.to_timedelta(durations))]
Out[24]: '14d'

pd.to_timedeltatransforma uma string em uma duração ( origem ) e np.argmaxretorna o índice do elemento mais alto.

Nicolas Gervais
fonte
Embora eu não vá usar numpy e / ou pandas para o projeto, estou tendo esse problema, mas devo dizer que é um exemplo incrível de uso eficiente das funções da biblioteca para realizar seu trabalho.
Rafiul Sabbir 17/01
4

Aqui está um truque absoluto que resolve o problema de uma maneira ruim, mas inteligente: o Python mine as maxfunções podem ser usadas com uma keyfunção usada para comparar elementos, para que ele retorne o elemento, minimizando ou maximizando essa função. Se a keyfunção retornar uma tupla, a ordem será determinada pelo primeiro componente da tupla, usando o segundo componente como desempatador.

Podemos explorar o fato de que o último caracteres 'd', 'h'e 'm'pode ser comparado em ordem alfabética; um d ay é mais longo do que um h a é mais do que um m inute. Isso significa que a duração mais longa tem o caractere mínimo em ordem alfabética, com o número inteiro máximo como desempate. Maximizar esse número inteiro é o mesmo que minimizar sua negação:

>>> durations = ['5d', '20h', '1h', '7m', '14d', '1m']
>>> min(durations, key=lambda d: (d[-1], -int(d[:-1])))
'14d'
kaya3
fonte
Você poderia ter segundos representados como s, e semanas como We meses como M, e ainda funcionaria; o hack quebra se você incluir anos como um you outro Y. Também depende de não haver durações, como 10000000monde uma unidade maior poderia ser usada; Estou assumindo que as strings são a saída de alguma API que sempre usa a maior unidade possível.
kaya3 17/01
3
lst = ['5d', '20h', '1h', '7m', '14d', '1m']
max(lst, key=lambda s: (-ord(s[-1]), int(s[:-1])))

Resultado:

'14d'

Útil para esse conjunto específico de strings, mas se o formato for diferente, será necessário ajustar o primeiro elemento da tupla de acordo. Agora faz sentido porque s> m> h> d.

torre
fonte
3

aqui está uma solução com expressão regular

import numpy as np
import re

new_list = []
x=['5d', '20h', '1h', '7m', '14d', '1m']
map_time={"d":1440, "h":60, "m":1}

for item in x:
    letter=re.findall("[a-zA-Z]+",item)
    number=re.findall("[1-9]+",item)
    new_list.append(map_time[letter[0]]*int(number[0]))

x[np.argmax(new_list)]
Kingindanord
fonte
2

Desde que seus horários sejam bem-formados, você poderá encontrar o com maxbase em uma única expressão regular:

>>> import re
>>>
>>> durations = ['5d', '20h', '1h', '7m', '14d', '1m']
>>> pattern = re.compile(r'(?:(\d*)d)?(?:(\d*)h)?(?:(\d*)m)?')
>>> max(inp, key=lambda tme: tuple(map(int, pattern.match(tme).groups(default=0))))
'14d'

A expressão regular cria uma tupla de dias, horas, minutos como seqüências de caracteres. O tuple(map(int, ...))converte em números inteiros. maxescolhe a maior dessas tuplas, que naturalmente pesam dias mais fortes que as horas que duram que os minutos.

MisterMiyagi
fonte
1

Uma maneira possível:

duration = ['5d', '20h', '1h', '7m', '14d', '1m', '2d']
duration_std = [0]*len(duration)

equivalence = {"d":60*60*24, "h":60*60, "m":60}

for idx, val in enumerate(duration):
    duration_std[idx] = int(val[:-1])*equivalence[val[-1]]

print(duration[duration_std.index(max(duration_std))])

Resultado

"14d"
Clemente
fonte