Obtenga la mayor duración de una lista de cadenas

8

Tengo una lista de duraciones como a continuación

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

donde destá parado por días, hestá parado por horas y mestá parado por minutos.

Quiero obtener la mayor duración de esta lista ( 14den este caso). ¿Cómo puedo obtener eso de esta lista de cadenas?

Rafiul Sabbir
fuente
1
stackoverflow.com/a/4628148/1224467 Esta respuesta tiene una solución para convertir sus cadenas en timedeltas. Estos pueden ser ordenados.
H4kor

Respuestas:

12

Solución de pitón puro. Podíamos guardar correspondencia entre nuestras extensiones de tiempo ( m, h, d) y minutos (aquí time_map), para encontrar mayor duración. Aquí estamos utilizando max()con keyargumento para aplicar nuestro mapeo.

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
fuente
14

np.argmaxen 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_timedeltaconvierte una cadena en una duración ( fuente ) y np.argmaxdevuelve el índice del elemento más alto.

Nicolas Gervais
fuente
Aunque no voy a usar numpy y / o pandas para el proyecto, estoy teniendo este problema, pero debo decir que es un ejemplo increíble de usar las funciones de la biblioteca de manera eficiente para hacer su trabajo.
Rafiul Sabbir
4

Aquí hay un truco absoluto que resuelve el problema de una manera mala pero inteligente: Python miny las maxfunciones se pueden usar con una keyfunción que se usa para comparar elementos, de modo que devuelva el elemento minimizando o maximizando esa función. Si la keyfunción devuelve una tupla, el primer componente de la tupla determina el orden, utilizando el segundo componente como un desempate.

Podemos explotar el hecho de que los últimos caracteres 'd', 'h'y 'm'se pueden comparar en orden alfabético; un d ay es más largo que una hora nuestra es más largo que un m inute. Esto significa que la duración más larga tiene el carácter mínimo en orden alfabético, con el número entero máximo como un desempate. Maximizar ese entero es lo mismo que minimizar su negación:

>>> durations = ['5d', '20h', '1h', '7m', '14d', '1m']
>>> min(durations, key=lambda d: (d[-1], -int(d[:-1])))
'14d'
kaya3
fuente
Podrías tener segundos representados como s, y semanas como Wy meses como M, y todavía funcionaría; Sin embargo, el truco se rompe si incluye años como yo Y. También se basa en que no haya duraciones como 10000000mdonde podría usarse una unidad más grande; Supongo que las cadenas son el resultado de alguna API que siempre usa la unidad más grande posible.
kaya3
3
lst = ['5d', '20h', '1h', '7m', '14d', '1m']
max(lst, key=lambda s: (-ord(s[-1]), int(s[:-1])))

Salida:

'14d'

Útil para este conjunto particular de cadenas, pero si el formato difiere, deberá ajustar el primer elemento de la tupla en consecuencia. En este momento tiene sentido porque s> m> h> d.

torre
fuente
3

aquí hay una solución con expresión 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
fuente
2

Siempre que sus tiempos estén bien formados, puede encontrarlos maxbasados ​​en una sola expresión 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'

La expresión regular crea una tupla de días, horas, minutos como cadenas. El lo tuple(map(int, ...))convierte a enteros. maxelige la más grande de estas tuplas, que naturalmente pesan días más fuertes que las horas más largas que los minutos.

MisterMiyagi
fuente
1

Una forma posible:

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))])

Salida

"14d"
Clemente
fuente